From ffa1f4b067fdfc7ec8ca4033ac3bf97f2b8073b7 Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Fri, 7 Jun 2019 15:10:11 -0400 Subject: [PATCH] Extend CAS interface with Write-only cache mode Write-only (WO) cache mode is similar to Write-back (WB), however read operations do not promote data to cache. Reads are mostly serviced by the core device, only dirty sectors are fetched from the cache. Write-only cache mode is behaving similarly to Write-back with respect to flushing dirty data. For example it is required to explicitly enable/disable flushing when changing cache mode from WO to something other than WB. Signed-off-by: Adam Rutkowski --- casadm/cas_lib.c | 15 +++++++++++---- casadm/cas_lib.h | 16 ++++++++-------- casadm/cas_main.c | 2 +- casadm/statistics_model.c | 5 ++--- ocf | 2 +- utils/casadm.8 | 7 +++++++ utils/opencas.py | 2 +- 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 94180d2..6233ccf 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -254,6 +254,7 @@ static struct name_to_val_mapping cache_mode_names[] = { #ifdef WI_AVAILABLE { .short_name = "wi", .long_name = "Write-Invalidate", .value = ocf_cache_mode_wi }, #endif + { .short_name = "wo", .long_name = "Write-Only", .value = ocf_cache_mode_wo }, { NULL } }; @@ -1062,6 +1063,7 @@ int set_cache_mode(unsigned int cache_mode, unsigned int cache_id, int flush) int fd = 0; int orig_mode; struct kcas_set_cache_state cmd; + bool flush_param_required; fd = open_ctrl_device(); if (fd == -1) @@ -1073,9 +1075,13 @@ int set_cache_mode(unsigned int cache_mode, unsigned int cache_id, int flush) return FAILURE; } - /* if flushing mode is undefined, set it to default (but only if original mode is write back mode) */ + /* If flushing mode is undefined, set it to default unless we're transitioning + * out of lazy write cache mode (like WB or WO), in which case user must explicitly + * state his preference */ + flush_param_required = ocf_mngt_cache_mode_has_lazy_write(orig_mode) && + !ocf_mngt_cache_mode_has_lazy_write(cache_mode); if (-1 == flush) { - if (ocf_cache_mode_wb == orig_mode) { + if (flush_param_required) { cas_printf(LOG_ERR, "Error: Required parameter (‘--flush-cache’) was not specified.\n"); close(fd); return FAILURE; @@ -1084,14 +1090,15 @@ int set_cache_mode(unsigned int cache_mode, unsigned int cache_id, int flush) } } - if (ocf_cache_mode_wb == orig_mode) { + if (flush_param_required) { if (1 == flush) { cas_printf(LOG_INFO, "CAS is currently flushing dirty data to primary storage devices.\n"); } else { - cas_printf(LOG_INFO, "CAS is currently migrating from Write-Back to %s mode.\n" + cas_printf(LOG_INFO, "CAS is currently migrating from %s to %s mode.\n" "Dirty data are being flushed to primary storage device in background.\n" "Please find flushing progress via list caches command (‘casadm -L’) or\n" "via statistics command (‘casadm -P’).\n", + cache_mode_to_name_long(orig_mode), cache_mode_to_name_long(cache_mode)); } } diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 59e17cf..642198c 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -125,15 +125,15 @@ int start_cache(ocf_cache_id_t cache_id, unsigned int cache_init, int stop_cache(ocf_cache_id_t cache_id, int flush); #ifdef WI_AVAILABLE -#define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt|wi" -#define CAS_CLI_HELP_SET_CACHE_MODES "wt|wb|wa|pt|wi" -#define CAS_CLI_HELP_SET_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Invalidate" -#define CAS_CLI_HELP_START_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Invalidate" +#define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt|wi|wo" +#define CAS_CLI_HELP_SET_CACHE_MODES "wt|wb|wa|pt|wi|wo" +#define CAS_CLI_HELP_SET_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Invalidate, Write-Only" +#define CAS_CLI_HELP_START_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Invalidate, Write-Only" #else -#define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt" -#define CAS_CLI_HELP_SET_CACHE_MODES "wt|wb|wa|pt" -#define CAS_CLI_HELP_START_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through" -#define CAS_CLI_HELP_SET_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through" +#define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt|wo" +#define CAS_CLI_HELP_SET_CACHE_MODES "wt|wb|wa|pt|wo" +#define CAS_CLI_HELP_START_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Only" +#define CAS_CLI_HELP_SET_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Only" #endif /** diff --git a/casadm/cas_main.c b/casadm/cas_main.c index b2a6359..ee8693a 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -900,7 +900,7 @@ int handle_get_param() static cli_option set_state_cache_mode_options[] = { {'c', "cache-mode", "Cache mode. Available cache modes: {"CAS_CLI_HELP_SET_CACHE_MODES"}", 1, "NAME", CLI_OPTION_REQUIRED}, {'i', "cache-id", CACHE_ID_DESC, 1, "ID", CLI_OPTION_REQUIRED}, - {'f', "flush-cache", "Flush all dirty data from cache before switching to new mode. Option is required when switching from Write-Back mode", 1, "yes|no",0}, + {'f', "flush-cache", "Flush all dirty data from cache before switching to new mode. Option is required when switching from Write-Back or Write-Only mode", 1, "yes|no",0}, {0}, }; diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index b98a9eb..08cae9a 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -911,9 +911,8 @@ int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info, return FAILURE; print_kv_pair(outfile, "Inactive Core Devices", "%d", inactive_cores); - print_kv_pair(outfile, "Write Policy", "%s%s", - (flush_progress && cache_info->info.cache_mode != ocf_cache_mode_wb) - ? "wb->" : "", cache_mode_to_name(cache_info->info.cache_mode)); + print_kv_pair(outfile, "Write Policy", "%s", + cache_mode_to_name(cache_info->info.cache_mode)); print_kv_pair(outfile, "Eviction Policy", "%s", eviction_policy_to_name(cache_info->info.eviction_policy)); print_kv_pair(outfile, "Cleaning Policy", "%s", diff --git a/ocf b/ocf index 75ec3c7..aeaeafb 160000 --- a/ocf +++ b/ocf @@ -1 +1 @@ -Subproject commit 75ec3c7db424e11b6e5fbde5f5afba12b824f849 +Subproject commit aeaeafb639ee20f0320ed859efd4a002810f141d diff --git a/utils/casadm.8 b/utils/casadm.8 index 36637d3..9bb0eea 100644 --- a/utils/casadm.8 +++ b/utils/casadm.8 @@ -62,6 +62,13 @@ to the core device. Pass-Through mode may be used in case if user doesn't want t cache any workload, for example in case if there are some maintenance operations causing cache pollution. +.TP +.B Write-Only (wo) +In Write-Only mode write operations are handled exactly like in Write-Back mode. Read +operations do not promote data to cache. Reads are typically serviced by the core +device, unless corresponding cache lines are dirty. + + .SH COMMANDS .TP .B -S, --start-cache diff --git a/utils/opencas.py b/utils/opencas.py index 7a9a527..b0e7900 100644 --- a/utils/opencas.py +++ b/utils/opencas.py @@ -261,7 +261,7 @@ class cas_config(object): format(self.device)) def check_cache_mode_valid(self, cache_mode): - if cache_mode.lower() not in ['wt', 'pt', 'wa', 'wb']: + if cache_mode.lower() not in ['wt', 'pt', 'wa', 'wb', 'wo']: raise ValueError('Invalid cache mode {0}'.format(cache_mode)) def check_cleaning_policy_valid(self, cleaning_policy):