diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index ef0a33b..fb4a42f 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -265,6 +265,12 @@ static struct name_to_val_mapping cleaning_policy_names[] = { { NULL } }; +static struct name_to_val_mapping promotion_policy_names[] = { + { .short_name = "always", .value = ocf_promotion_always }, + { .short_name = "nhit", .value = ocf_promotion_nhit }, + { NULL} +}; + static struct name_to_val_mapping metadata_mode_names[] = { { .short_name = "normal", .value = CAS_METADATA_MODE_NORMAL }, { .short_name = "atomic", .value = CAS_METADATA_MODE_ATOMIC }, @@ -434,6 +440,16 @@ inline const char *cleaning_policy_to_name(uint8_t policy) return val_to_short_name(policy, cleaning_policy_names, "Unknown"); } +inline int validate_str_promotion_policy(const char *s) +{ + return validate_str_val_mapping(s, promotion_policy_names, -1); +} + +inline const char *promotion_policy_to_name(uint8_t policy) +{ + return val_to_short_name(policy, promotion_policy_names, "Unknown"); +} + const char *metadata_mode_to_name(uint8_t metadata_mode) { return val_to_short_name(metadata_mode, metadata_mode_names, "Invalid"); @@ -707,6 +723,7 @@ struct cache_device *get_cache_device(const struct kcas_cache_info *info) cache->flushed = info->info.flushed; cache->eviction_policy = info->info.eviction_policy; cache->cleaning_policy = info->info.cleaning_policy; + cache->promotion_policy = info->info.promotion_policy; cache->size = info->info.cache_line_size; if ((info->info.state & (1 << ocf_cache_state_running)) == 0) { diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index a4bc266..cc545ac 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -44,6 +44,7 @@ struct cache_device { int mode; int eviction_policy; int cleaning_policy; + int promotion_policy; int dirty; int flushed; unsigned size; @@ -92,6 +93,7 @@ enum metadata_mode_t { const char *eviction_policy_to_name(uint8_t policy); const char *cleaning_policy_to_name(uint8_t policy); +const char *promotion_policy_to_name(uint8_t policy); const char *cache_mode_to_name(uint8_t cache_mode); const char *get_cache_state_name(int cache_state); const char *get_core_state_name(int core_state); @@ -256,6 +258,7 @@ int validate_path(const char *path, int exist); int validate_str_cache_mode(const char *s); int validate_str_ev_policy(const char *s); int validate_str_cln_policy(const char *s); +int validate_str_promotion_policy(const char *s); int validate_str_meta_variant(const char *s); int validate_str_stats_filters(const char* s); int validate_str_output_format(const char* s); diff --git a/casadm/cas_main.c b/casadm/cas_main.c index 8fb8393..8258069 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -50,6 +50,7 @@ struct command_args{ int cache_state_flush; int flush_data; int cleaning_policy_type; + int promotion_policy_type; int script_subcmd; int try_add; int update_path; @@ -75,6 +76,7 @@ static struct command_args command_args_values = { .cache_state_flush = UNDEFINED, /* three state logic: YES NO UNDEFINED */ .flush_data = 1, .cleaning_policy_type = 0, + .promotion_policy_type = 0, .script_subcmd = -1, .try_add = false, .update_path = false, @@ -560,6 +562,12 @@ static char *cleaning_policy_type_values[] = { NULL, }; +static char *promotion_policy_type_values[] = { + [ocf_promotion_always] = "always", + [ocf_promotion_nhit] = "nhit", + NULL, +}; + static struct cas_param cas_cache_params[] = { /* Cleaning policy type */ [cache_param_cleaning_policy_type] = { @@ -588,6 +596,20 @@ static struct cas_param cas_cache_params[] = { [cache_param_cleaning_acp_flush_max_buffers] = { .name = "Flush max buffers" , }, + + /* Promotion policy type */ + [cache_param_promotion_policy_type] = { + .name = "Promotion policy type", + .value_names = promotion_policy_type_values, + }, + + /*Promotion policy NHIT params */ + [cache_param_promotion_nhit_insertion_threshold] = { + .name = "Insertion threshold", + }, + [cache_param_promotion_nhit_trigger_threshold] = { + .name = "Policy trigger [%]", + }, {0}, }; @@ -614,6 +636,15 @@ static struct cas_param cas_cache_params[] = { #define CLEANING_ACP_MAX_BUFFERS_DESC "Number of cache lines flushed in single ACP cleaning thread iteration" \ " <%d-%d> (default: %d)" +#define PROMOTION_POLICY_TYPE_DESC "Promotion policy type. "\ + "Available policy types: {always|nhit}" + +#define PROMOTION_NHIT_TRIGGER_DESC "Cache occupancy value over which NHIT promotion is active " \ + "<%d-%d>[%] (default: %d%)" + +#define PROMOTION_NHIT_THRESHOLD_DESC "Number of requests for given core line " \ + "after which NHIT policy allows insertion into cache <%d-%d> (default: %d)" + static cli_namespace set_param_namespace = { .short_name = 'n', .long_name = "name", @@ -627,6 +658,21 @@ static cli_namespace set_param_namespace = { {'p', "policy", CLEANING_POLICY_TYPE_DESC, 1, "POLICY", 0}, CACHE_PARAMS_NS_END() + CACHE_PARAMS_NS_BEGIN("promotion", "Promotion policy parameters") + {'p', "policy", PROMOTION_POLICY_TYPE_DESC, 1, "POLICY", 0}, + CACHE_PARAMS_NS_END() + + CACHE_PARAMS_NS_BEGIN("promotion-nhit", "Promotion policy NHIT parameters") + {'t', "threshold", PROMOTION_NHIT_THRESHOLD_DESC, 1, "NUMBER", + CLI_OPTION_RANGE_INT | CLI_OPTION_DEFAULT_INT, + OCF_NHIT_MIN_THRESHOLD, OCF_NHIT_MAX_THRESHOLD, + OCF_NHIT_THRESHOLD_DEFAULT}, + {'o', "trigger", PROMOTION_NHIT_TRIGGER_DESC, 1, "NUMBER", + CLI_OPTION_RANGE_INT | CLI_OPTION_DEFAULT_INT, + OCF_NHIT_MIN_TRIGGER, OCF_NHIT_MAX_TRIGGER, + OCF_NHIT_TRIGGER_DEFAULT}, + CACHE_PARAMS_NS_END() + CACHE_PARAMS_NS_BEGIN("cleaning-alru", "Cleaning policy ALRU parameters") {'w', "wake-up", CLEANING_ALRU_WAKE_UP_DESC, 1, "NUMBER", CLI_OPTION_RANGE_INT | CLI_OPTION_DEFAULT_INT, @@ -772,6 +818,49 @@ int set_param_cleaning_acp_handle_option(char *opt, const char **arg) SET_CACHE_PARAM(cache_param_cleaning_acp_flush_max_buffers, strtoul(arg[0], NULL, 10)); + } + + return FAILURE; +} + +int set_param_promotion_handle_option(char *opt, const char **arg) +{ + if (!strcmp(opt, "policy")) { + if (!strcmp("always", arg[0])) { + SET_CACHE_PARAM(cache_param_promotion_policy_type, + ocf_promotion_always); + } else if (!strcmp("nhit", arg[0])) { + SET_CACHE_PARAM(cache_param_promotion_policy_type, + ocf_promotion_nhit); + } else { + cas_printf(LOG_ERR, "Error: Invalid policy name.\n"); + return FAILURE; + } + } else { + return FAILURE; + } + + return SUCCESS; +} + +int set_param_promotion_nhit_handle_option(char *opt, const char **arg) +{ + if (!strcmp(opt, "threshold")) { + if (validate_str_num(arg[0], "threshold", + OCF_NHIT_MIN_THRESHOLD, OCF_NHIT_MAX_THRESHOLD)) { + return FAILURE; + } + + SET_CACHE_PARAM(cache_param_promotion_nhit_insertion_threshold, + strtoul(arg[0], NULL, 10)); + } else if (!strcmp(opt, "trigger")) { + if (validate_str_num(arg[0], "trigger", + OCF_NHIT_MIN_TRIGGER, OCF_NHIT_MAX_THRESHOLD)) { + return FAILURE; + } + + SET_CACHE_PARAM(cache_param_promotion_nhit_trigger_threshold, + strtoul(arg[0], NULL, 10)); } else { return FAILURE; } @@ -793,6 +882,12 @@ int set_param_namespace_handle_option(char *namespace, char *opt, const char **a } else if (!strcmp(namespace, "cleaning-acp")) { return cache_param_handle_option_generic(opt, arg, set_param_cleaning_acp_handle_option); + } else if (!strcmp(namespace, "promotion")) { + return cache_param_handle_option_generic(opt, arg, + set_param_promotion_handle_option); + } else if (!strcmp(namespace, "promotion-nhit")) { + return cache_param_handle_option_generic(opt, arg, + set_param_promotion_nhit_handle_option); } else { return FAILURE; } @@ -831,6 +926,8 @@ static cli_namespace get_param_namespace = { GET_CACHE_PARAMS_NS("cleaning", "Cleaning policy parameters") GET_CACHE_PARAMS_NS("cleaning-alru", "Cleaning policy ALRU parameters") GET_CACHE_PARAMS_NS("cleaning-acp", "Cleaning policy ACP parameters") + GET_CACHE_PARAMS_NS("promotion", "Promotion policy parameters") + GET_CACHE_PARAMS_NS("promotion-nhit", "Promotion policy NHIT parameters") {0}, }, @@ -872,6 +969,15 @@ int get_param_namespace_handle_option(char *namespace, char *opt, const char **a SELECT_CACHE_PARAM(cache_param_cleaning_acp_flush_max_buffers); return cache_param_handle_option_generic(opt, arg, get_param_handle_option); + } else if (!strcmp(namespace, "promotion")) { + SELECT_CACHE_PARAM(cache_param_promotion_policy_type); + return cache_param_handle_option_generic(opt, arg, + get_param_handle_option); + } else if (!strcmp(namespace, "promotion-nhit")) { + SELECT_CACHE_PARAM(cache_param_promotion_nhit_insertion_threshold); + SELECT_CACHE_PARAM(cache_param_promotion_nhit_trigger_threshold); + return cache_param_handle_option_generic(opt, arg, + get_param_handle_option); } else { return FAILURE; } diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index 72c0a77..cba80f9 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -548,6 +548,8 @@ int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info, eviction_policy_to_name(cache_info->info.eviction_policy)); print_kv_pair(outfile, "Cleaning Policy", "%s", cleaning_policy_to_name(cache_info->info.cleaning_policy)); + print_kv_pair(outfile, "Promotion Policy", "%s", + promotion_policy_to_name(cache_info->info.promotion_policy)); print_kv_pair(outfile, "Cache line size", "%llu, [KiB]", cache_info->info.cache_line_size / KiB);