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 <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski 2019-06-07 15:10:11 -04:00
parent a9eb0ee705
commit ffa1f4b067
7 changed files with 31 additions and 18 deletions

View File

@ -254,6 +254,7 @@ static struct name_to_val_mapping cache_mode_names[] = {
#ifdef WI_AVAILABLE #ifdef WI_AVAILABLE
{ .short_name = "wi", .long_name = "Write-Invalidate", .value = ocf_cache_mode_wi }, { .short_name = "wi", .long_name = "Write-Invalidate", .value = ocf_cache_mode_wi },
#endif #endif
{ .short_name = "wo", .long_name = "Write-Only", .value = ocf_cache_mode_wo },
{ NULL } { NULL }
}; };
@ -1062,6 +1063,7 @@ int set_cache_mode(unsigned int cache_mode, unsigned int cache_id, int flush)
int fd = 0; int fd = 0;
int orig_mode; int orig_mode;
struct kcas_set_cache_state cmd; struct kcas_set_cache_state cmd;
bool flush_param_required;
fd = open_ctrl_device(); fd = open_ctrl_device();
if (fd == -1) if (fd == -1)
@ -1073,9 +1075,13 @@ int set_cache_mode(unsigned int cache_mode, unsigned int cache_id, int flush)
return FAILURE; 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 (-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"); cas_printf(LOG_ERR, "Error: Required parameter (--flush-cache) was not specified.\n");
close(fd); close(fd);
return FAILURE; 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) { if (1 == flush) {
cas_printf(LOG_INFO, "CAS is currently flushing dirty data to primary storage devices.\n"); cas_printf(LOG_INFO, "CAS is currently flushing dirty data to primary storage devices.\n");
} else { } 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" "Dirty data are being flushed to primary storage device in background.\n"
"Please find flushing progress via list caches command (casadm -L) or\n" "Please find flushing progress via list caches command (casadm -L) or\n"
"via statistics command (casadm -P).\n", "via statistics command (casadm -P).\n",
cache_mode_to_name_long(orig_mode),
cache_mode_to_name_long(cache_mode)); cache_mode_to_name_long(cache_mode));
} }
} }

View File

@ -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); int stop_cache(ocf_cache_id_t cache_id, int flush);
#ifdef WI_AVAILABLE #ifdef WI_AVAILABLE
#define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt|wi" #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" #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" #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" #define CAS_CLI_HELP_START_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Invalidate, Write-Only"
#else #else
#define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt" #define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt|wo"
#define CAS_CLI_HELP_SET_CACHE_MODES "wt|wb|wa|pt" #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" #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" #define CAS_CLI_HELP_SET_CACHE_MODES_FULL "Write-Through, Write-Back, Write-Around, Pass-Through, Write-Only"
#endif #endif
/** /**

View File

@ -900,7 +900,7 @@ int handle_get_param()
static cli_option set_state_cache_mode_options[] = { 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}, {'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}, {'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}, {0},
}; };

View File

@ -911,9 +911,8 @@ int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info,
return FAILURE; return FAILURE;
print_kv_pair(outfile, "Inactive Core Devices", "%d", inactive_cores); print_kv_pair(outfile, "Inactive Core Devices", "%d", inactive_cores);
print_kv_pair(outfile, "Write Policy", "%s%s", print_kv_pair(outfile, "Write Policy", "%s",
(flush_progress && cache_info->info.cache_mode != ocf_cache_mode_wb) cache_mode_to_name(cache_info->info.cache_mode));
? "wb->" : "", cache_mode_to_name(cache_info->info.cache_mode));
print_kv_pair(outfile, "Eviction Policy", "%s", print_kv_pair(outfile, "Eviction Policy", "%s",
eviction_policy_to_name(cache_info->info.eviction_policy)); eviction_policy_to_name(cache_info->info.eviction_policy));
print_kv_pair(outfile, "Cleaning Policy", "%s", print_kv_pair(outfile, "Cleaning Policy", "%s",

2
ocf

@ -1 +1 @@
Subproject commit 75ec3c7db424e11b6e5fbde5f5afba12b824f849 Subproject commit aeaeafb639ee20f0320ed859efd4a002810f141d

View File

@ -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 cache any workload, for example in case if there are some maintenance operations
causing cache pollution. 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 .SH COMMANDS
.TP .TP
.B -S, --start-cache .B -S, --start-cache

View File

@ -261,7 +261,7 @@ class cas_config(object):
format(self.device)) format(self.device))
def check_cache_mode_valid(self, cache_mode): 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)) raise ValueError('Invalid cache mode {0}'.format(cache_mode))
def check_cleaning_policy_valid(self, cleaning_policy): def check_cleaning_policy_valid(self, cleaning_policy):