diff --git a/casadm/argp.h b/casadm/argp.h index 91c8b77..53bedaa 100644 --- a/casadm/argp.h +++ b/casadm/argp.h @@ -16,7 +16,8 @@ enum CLI_OPTION_FLAGS { CLI_OPTION_HIDDEN = 1 << 1, CLI_OPTION_RANGE_INT = 1 << 2, /*! if option has a min/max value */ CLI_OPTION_DEFAULT_INT = 1 << 3, /*! if option has a default value */ - CLI_OPTION_OPTIONAL_ARG = 1 << 4 /*! if option argument is optional */ + CLI_OPTION_OPTIONAL_ARG = 1 << 4, /*! if option argument is optional */ + CLI_OPTION_SUBCMD = 1 << 5 /*! if option is a subcmd */ }; enum CLI_COMMAND_FLAGS { diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 9b08437..25ca4b7 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -774,7 +774,7 @@ struct cache_device *get_cache_device(const struct kcas_cache_info *info, bool b cache_size = sizeof(*cache); cache_size += info->info.core_count * sizeof(cache->cores[0]); - if (info->info.failover_detached) + if (info->info.standby_detached) return NULL; cache = (struct cache_device *) malloc(cache_size); @@ -2993,24 +2993,50 @@ int cas_ioctl(int id, void *data) } -int failover_detach(int cache_id) +int standby_init(int cache_id, ocf_cache_line_size_t line_size, + const char *cache_device, int force) { - struct kcas_failover_detach data = {.cache_id = cache_id}; - - return cas_ioctl(KCAS_IOCTL_FAILOVER_DETACH, &data); + return start_cache(cache_id, + CACHE_INIT_STANDBY_NEW, + cache_device, + ocf_cache_mode_default, + line_size, + force); } -int failover_activate(int cache_id, const char *cache_device) +int standby_load(int cache_id, ocf_cache_line_size_t line_size, + const char *cache_device) { - struct kcas_failover_activate data = {.cache_id = cache_id}; + return start_cache(cache_id, + CACHE_INIT_STANDBY_LOAD, + cache_device, + ocf_cache_mode_default, + line_size, + 0); +} - if (set_device_path(data.cache_path, sizeof(data.cache_path), +int standby_detach(int cache_id) +{ + struct kcas_standby_detach cmd = { + .cache_id = cache_id + }; + + return cas_ioctl(KCAS_IOCTL_STANDBY_DETACH, &cmd); +} + +int standby_activate(int cache_id, const char *cache_device) +{ + struct kcas_standby_activate cmd = { + .cache_id = cache_id + }; + + if (set_device_path(cmd.cache_path, sizeof(cmd.cache_path), cache_device, MAX_STR_LEN) != SUCCESS) { return FAILURE; } - if (cas_ioctl(KCAS_IOCTL_FAILOVER_ACTIVATE, &data) != SUCCESS) { - print_err(data.ext_err_code ? : KCAS_ERR_SYSTEM); + if (cas_ioctl(KCAS_IOCTL_STANDBY_ACTIVATE, &cmd) != SUCCESS) { + print_err(cmd.ext_err_code ? : KCAS_ERR_SYSTEM); return FAILURE; } diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 066859c..afc7d4b 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -204,6 +204,31 @@ int get_core_info(int fd, int cache_id, int core_id, struct kcas_core_info *info int remove_core(unsigned int cache_id, unsigned int core_id, bool detach, bool force_no_flush); +/** + * @brief initialize failover standby cache instance + * + * @param cache_id cache instance identifier + * @param line_size cache line size + * @param cache_device path to caching device + * @param force discard pre-existing metadata + * + * @return 0 upon successful detach, 1 upon failure + */ +int standby_init(int cache_id, ocf_cache_line_size_t line_size, + const char *cache_device, int force); + +/** + * @brief load failover standby cache instance + * + * @param cache_id cache instance identifier + * @param line_size cache line size + * @param cache_device path to caching device + * + * @return 0 upon successful detach, 1 upon failure + */ +int standby_load(int cache_id, ocf_cache_line_size_t line_size, + const char *cache_device); + /** * @brief detach caching device from failover standby cache instance * @@ -211,7 +236,7 @@ int remove_core(unsigned int cache_id, unsigned int core_id, * * @return 0 upon successful detach, 1 upon failure */ -int failover_detach(int cache_id); +int standby_detach(int cache_id); /** * @brief activate failover standby cache instance @@ -221,7 +246,7 @@ int failover_detach(int cache_id); * * @return 0 upon successful detach, 1 upon failure */ -int failover_activate(int cache_id, const char *cache_device); +int standby_activate(int cache_id, const char *cache_device); /** * @brief remove inactive core device from a cache diff --git a/casadm/cas_main.c b/casadm/cas_main.c index e15f7c0..e9eaafe 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -154,6 +154,84 @@ int command_handle_option(char *opt, const char **arg) return SUCCESS; } +/* Filler to print sub-commands */ +int cmd_subcmd_print_subcmd(cli_option* option, int flag) +{ + return !!(option->flags & CLI_OPTION_SUBCMD); +} + +/* Filler to print parameters of given sub-command */ +int cmd_subcmd_print_param(cli_option* option, int flag) +{ + return (flag == (option->priv & flag)); +} + +static inline void cmd_subcmd_print_invalid_subcmd(cli_option* options) +{ + cas_printf(LOG_ERR, "Invalid or missing first sub-command parameter. "); + cas_printf(LOG_ERR, "Expected one of the: {"); + print_options_usage(options, "|", cmd_subcmd_print_subcmd, 0); + cas_printf(LOG_ERR, "}\n"); +} + +/* Print help for command with subcommands */ +void cmd_subcmd_help(app *app_values, cli_command *cmd, int flag_required) +{ + int i, flag = 0, all_ops, printed_ops; + char option_name[MAX_STR_LEN]; + cli_option* iter = &(cmd->options[0]); + + /* Print usage */ + cas_printf(LOG_INFO, "Usage: %s --%s {", app_values->name, cmd->name); + print_options_usage(cmd->options, "|", cmd_subcmd_print_subcmd, 0); + cas_printf(LOG_INFO, "}\n\n"); + + print_command_header(app_values, cmd); + + for (;iter->long_name; iter++, flag++) { + if (!(iter->flags & CLI_OPTION_SUBCMD)) { + continue; + } + + cas_printf(LOG_INFO, "\n"); + + cas_printf(LOG_INFO, "%s:\n", iter->desc); + + cas_printf(LOG_INFO, "Usage: %s --%s --%s ", app_values->name, + cmd->name, iter->long_name); + + all_ops = printed_ops = 0; + for (i = 0; cmd->options[i].long_name != NULL; i++) { + if (0 == cmd->options[i].priv) { + continue; + } + + if (1 == cmd_subcmd_print_param(&cmd->options[i], (1 << flag))) { + all_ops++; + } else { + continue; + } + + if (1 == cmd_subcmd_print_param(&cmd->options[i], (1 << flag_required))) { + printed_ops++; + } + } + + print_options_usage(cmd->options, " ", cmd_subcmd_print_param, + (1 << flag) | (1 << flag_required)); + + if (all_ops != printed_ops) { + cas_printf(LOG_INFO, " [option...]"); + } + command_name_in_brackets(option_name, MAX_STR_LEN, iter->short_name, iter->long_name); + cas_printf(LOG_INFO, "\nOptions that are valid with %s are:\n", option_name); + + print_list_options(cmd->options, (1 << flag), cmd_subcmd_print_param); + + cas_printf(LOG_INFO, "\n"); + } +} + int remove_core_command_handle_option(char *opt, const char **arg) { if (!strcmp(opt, "cache-id")){ @@ -197,19 +275,8 @@ int start_cache_command_handle_option(char *opt, const char **arg) command_args_values.cache_id = atoi(arg[0]); } else if (!strcmp(opt, "load")) { - if (command_args_values.state == CACHE_INIT_STANDBY) { - cas_printf(LOG_ERR, "Use of 'failover-standby' and 'load' simultaneously is forbidden.\n"); - return FAILURE; - } command_args_values.state = CACHE_INIT_LOAD; - } else if (!strcmp(opt, "failover-standby")) { - if (command_args_values.state == CACHE_INIT_LOAD) { - cas_printf(LOG_ERR, "Use of 'failover-standby' and 'load' simultaneously is forbidden.\n"); - return FAILURE; - } - - command_args_values.state = CACHE_INIT_STANDBY; } else if (!strcmp(opt, "cache-device")) { if(validate_device_name(arg[0]) == FAILURE) return FAILURE; @@ -249,16 +316,16 @@ int start_cache_command_handle_option(char *opt, const char **arg) #define CACHE_DEVICE_DESC "Caching device to be used" #define CORE_DEVICE_DESC "Path to core device" +#define CACHE_LINE_SIZE_DESC "Set cache line size in kibibytes: {4,8,16,32,64}[KiB] (default: %d)" static cli_option start_options[] = { {'d', "cache-device", CACHE_DEVICE_DESC, 1, "DEVICE", CLI_OPTION_REQUIRED}, {'i', "cache-id", CACHE_ID_DESC_LONG, 1, "ID", 0}, {'l', "load", "Load cache metadata from caching device (DANGEROUS - see manual or Admin Guide for details)"}, - {'s', "failover-standby", "Start cache in standby mode for failover purpose (DANGEROUS - see manual or Admin Guide for details)"}, {'f', "force", "Force the creation of cache instance"}, {'c', "cache-mode", "Set cache mode from available: {"CAS_CLI_HELP_START_CACHE_MODES"} "CAS_CLI_HELP_START_CACHE_MODES_FULL"; without this parameter Write-Through will be set by default", 1, "NAME"}, - {'x', "cache-line-size", "Set cache line size in kibibytes: {4,8,16,32,64}[KiB] (default: %d)", 1, "NUMBER", CLI_OPTION_DEFAULT_INT, 0, 0, ocf_cache_line_size_default / KiB}, + {'x', "cache-line-size", CACHE_LINE_SIZE_DESC, 1, "NUMBER", CLI_OPTION_DEFAULT_INT, 0, 0, ocf_cache_line_size_default / KiB}, {0} }; @@ -344,32 +411,11 @@ int handle_start() return FAILURE; } - if (command_args_values.state == CACHE_INIT_STANDBY) { - if (command_args_values.force) { - cas_printf(LOG_ERR, "Use of 'failover-standby' and 'force' simultaneously is forbidden.\n"); - return FAILURE; - } - if (command_args_values.cache_id == OCF_CACHE_ID_INVALID) { - cas_printf(LOG_ERR, "Using 'failover-standby' requires specifying 'cache-id'.\n"); - return FAILURE; - } - } - if (command_args_values.line_size == ocf_cache_line_size_none) { - if (command_args_values.state == CACHE_INIT_STANDBY) { - cas_printf(LOG_ERR, "Using 'failover-standby' requires specifying 'cache-line-size'.\n"); - return FAILURE; - } - command_args_values.line_size = ocf_cache_line_size_default; } - if (command_args_values.cache_mode != ocf_cache_mode_none) { - if (command_args_values.state == CACHE_INIT_STANDBY) { - cas_printf(LOG_ERR, "It is not possible to use 'cache-mode' when using 'failover-standby'.\n"); - return FAILURE; - } - } else { + if (command_args_values.cache_mode == ocf_cache_mode_none) { command_args_values.cache_mode = ocf_cache_mode_default; } @@ -1261,7 +1307,7 @@ static cli_option io_class_params_options[] = { .args_count = 0, .arg = NULL, .priv = 0, - .flags = CLI_OPTION_DEFAULT_INT + .flags = CLI_OPTION_SUBCMD, }, [io_class_opt_subcmd_list] = { .short_name = 'L', @@ -1270,7 +1316,7 @@ static cli_option io_class_params_options[] = { .args_count = 0, .arg = NULL, .priv = 0, - .flags = CLI_OPTION_DEFAULT_INT, + .flags = CLI_OPTION_SUBCMD, }, [io_class_opt_cache_id] = { .short_name = 'i', @@ -1371,26 +1417,6 @@ struct { .output_format = OUTPUT_FORMAT_DEFAULT }; -/* Filler to print sub-commands */ -int io_class_print_subcmd(cli_option* options, int flag) -{ - return (0 == (options->flags & CLI_OPTION_DEFAULT_INT)) ? 0 : 1; -} - -/* Filler to print parameters of given sub-command */ -int io_class_print_param(cli_option* options, int flag) -{ - return (flag == (options->priv & flag)) ? 1 : 0; -} - -static inline void io_class_print_invalid_subcmd(void) -{ - cas_printf(LOG_ERR, "Invalid or missing first sub-command parameter "); - cas_printf(LOG_ERR, "Expected one of the: {"); - print_options_usage(io_class_params_options, "|", io_class_print_subcmd, 0); - cas_printf(LOG_INFO, "}\n"); -} - /* Parser of option for IO class command */ int io_class_handle_option(char *opt, const char **arg) { @@ -1468,7 +1494,7 @@ int io_class_is_missing() { int io_class_handle() { /* Check if sub-command was specified */ if (io_class_opt_subcmd_unknown == io_class_params.subcmd) { - io_class_print_invalid_subcmd(); + cmd_subcmd_print_invalid_subcmd(io_class_params_options); return FAILURE; } @@ -1489,17 +1515,10 @@ int io_class_handle() { return FAILURE; } - -static cli_option failover_detach_options[] = { - {'i', "cache-id", CACHE_ID_DESC, 1, "ID", CLI_OPTION_REQUIRED}, - {} -}; - -static cli_option failover_activate_options[] = { - {'i', "cache-id", CACHE_ID_DESC, 1, "ID", CLI_OPTION_REQUIRED}, - {'d', "cache-device", CACHE_DEVICE_DESC, 1, "DEVICE", CLI_OPTION_REQUIRED}, - {} -}; +void io_class_help(app *app_values, cli_command *cmd) +{ + cmd_subcmd_help(app_values, cmd, io_class_opt_flag_required); +} /******************************************************************************* * Script Commands @@ -1736,17 +1755,6 @@ int script_command_is_valid() { return result; } -int handle_failover_detach() -{ - return failover_detach(command_args_values.cache_id); -} - -int handle_failover_activate() -{ - return failover_activate(command_args_values.cache_id, - command_args_values.cache_device); -} - int script_handle() { if (script_cmd_unknown == command_args_values.script_subcmd) { cas_printf(LOG_ERR, "Invalid or missing first sub-command parameter\n"); @@ -1852,65 +1860,257 @@ static int handle_version(void) return SUCCESS; } -/* Print help for IO class command */ -void io_class_help(app *app_values, cli_command *cmd) +static int handle_help(); + +/******************************************************************************* + * Standby commands + ******************************************************************************/ + +enum { + standby_opt_subcmd_init = 0, + standby_opt_subcmd_load, + standby_opt_subcmd_detach, + standby_opt_subcmd_activate, + + standby_opt_cache_id, + standby_opt_cache_line_size, + standby_opt_cache_device, + + standby_opt_force, + + standby_opt_flag_required, + standby_opt_flag_set, + + standby_opt_subcmd_unknown, +}; + +/* Standby command options */ +static cli_option standby_params_options[] = { + [standby_opt_subcmd_init] = { + .long_name = "init", + .desc = "Initialize cache in standby mode", + .args_count = 0, + .arg = NULL, + .priv = 0, + .flags = CLI_OPTION_SUBCMD, + }, + [standby_opt_subcmd_load] = { + .long_name = "load", + .desc = "Load cache in standby mode", + .args_count = 0, + .arg = NULL, + .priv = 0, + .flags = CLI_OPTION_SUBCMD, + }, + [standby_opt_subcmd_detach] = { + .long_name = "detach", + .desc = "Detach cache device in standby mode", + .args_count = 0, + .arg = NULL, + .priv = 0, + .flags = CLI_OPTION_SUBCMD, + }, + [standby_opt_subcmd_activate] = { + .long_name = "activate", + .desc = "Activate standby cache", + .args_count = 0, + .arg = NULL, + .priv = 0, + .flags = CLI_OPTION_SUBCMD, + }, + + [standby_opt_cache_id] = { + .short_name = 'i', + .long_name = "cache-id", + .desc = CACHE_ID_DESC, + .args_count = 1, + .arg = "ID", + .priv = (1 << standby_opt_subcmd_init) + | (1 << standby_opt_subcmd_load) + | (1 << standby_opt_subcmd_detach) + | (1 << standby_opt_subcmd_activate) + | (1 << standby_opt_flag_required), + .flags = CLI_OPTION_RANGE_INT, + .max_value = 0, + .min_value = OCF_CACHE_ID_MAX, + }, + [standby_opt_cache_line_size] = { + .short_name = 'x', + .long_name = "cache-line-size", + .desc = CACHE_LINE_SIZE_DESC, + .args_count = 1, + .arg = "NUMBER", + .priv = (1 << standby_opt_subcmd_init) + | (1 << standby_opt_subcmd_load) + | (1 << standby_opt_flag_required), + .flags = CLI_OPTION_DEFAULT_INT, + .default_value = ocf_cache_line_size_default / KiB, + }, + [standby_opt_cache_device] = { + .short_name = 'd', + .long_name = "cache-device", + .desc = CACHE_DEVICE_DESC, + .args_count = 1, + .arg = "DEVICE", + .priv = (1 << standby_opt_subcmd_init) + | (1 << standby_opt_subcmd_load) + | (1 << standby_opt_subcmd_activate) + | (1 << standby_opt_flag_required), + }, + + [standby_opt_force] = { + .short_name = 'f', + .long_name = "force", + .desc = "Force the initialization of cache instance", + .priv = (1 << standby_opt_subcmd_init), + }, + + {0} +}; + +struct { + int subcmd; + int cache_id; + int line_size; + const char* cache_device; + int force; +} static standby_params = { + .subcmd = standby_opt_subcmd_unknown, + .cache_id = OCF_CACHE_ID_INVALID, + .line_size = ocf_cache_line_size_none, + .cache_device = NULL, + .force = 0, +}; + +/* Parser of option for IO class command */ +int standby_handle_option(char *opt, const char **arg) { - int i, flag = 0, all_ops, printed_ops; - char option_name[MAX_STR_LEN]; - cli_option* iter = &(cmd->options[0]); + if (io_class_opt_subcmd_unknown == io_class_params.subcmd) { + /* First parameters which defines sub-command */ + if (!strcmp(opt, "init")) { + standby_params.subcmd = standby_opt_subcmd_init; + return 0; + } else if (!strcmp(opt, "load")) { + standby_params.subcmd = standby_opt_subcmd_load; + return 0; + } else if (!strcmp(opt, "detach")) { + standby_params.subcmd = standby_opt_subcmd_detach; + return 0; + } else if (!strcmp(opt, "activate")) { + standby_params.subcmd = standby_opt_subcmd_activate; + return 0; + } + } - /* Print usage */ - cas_printf(LOG_INFO, "Usage: %s --%s {", app_values->name, cmd->name); - print_options_usage(cmd->options, "|", io_class_print_subcmd, 0); - cas_printf(LOG_INFO, "}\n\n"); + if (!strcmp(opt, "cache-id")) { + if (validate_str_num(arg[0], "cache id", OCF_CACHE_ID_MIN, + OCF_CACHE_ID_MAX) == FAILURE) + return FAILURE; - print_command_header(app_values, cmd); + standby_params_options[standby_opt_cache_id].priv |= + (1 << standby_opt_flag_set); + standby_params.cache_id = atoi(arg[0]); + } else if (!strcmp(opt, "cache-line-size")) { + if (validate_str_num_sbd(arg[0], "cache line size", + ocf_cache_line_size_min / KiB, + ocf_cache_line_size_max / KiB) == FAILURE) + return FAILURE; - for (;iter->long_name; iter++, flag++) { - if (0 == (iter->flags & CLI_OPTION_DEFAULT_INT)) { + standby_params_options[standby_opt_cache_line_size].priv |= + (1 << standby_opt_flag_set); + standby_params.line_size = atoi((const char*)arg[0]) * KiB; + } else if (!strcmp(opt, "cache-device")) { + if (validate_device_name(arg[0]) == FAILURE) + return FAILURE; + + standby_params_options[standby_opt_cache_device].priv |= + (1 << standby_opt_flag_set); + standby_params.cache_device = arg[0]; + } else if (!strcmp(opt, "force")) { + standby_params_options[standby_opt_force].priv |= + (1 << standby_opt_flag_set); + standby_params.force = 1; + } + + return 0; +} + +/* Check if all required command were set depending on command type */ +int standby_is_missing() { + int result = 0; + int mask; + cli_option* iter = standby_params_options; + + for (;iter->long_name; iter++) { + char option_name[MAX_STR_LEN]; + if (!iter->priv) { continue; } - cas_printf(LOG_INFO, "\n"); - - cas_printf(LOG_INFO, "%s:\n", iter->desc); - - cas_printf(LOG_INFO, "Usage: %s --%s --%s ", app_values->name, - cmd->name, iter->long_name); - - all_ops = printed_ops = 0; - for (i = 0; cmd->options[i].long_name != NULL; i++) { - if (0 == cmd->options[i].priv) { - continue; - } - - if (1 == io_class_print_param(&cmd->options[i], (1 << flag))) { - all_ops++; - } else { - continue; - } - - if (1 == io_class_print_param(&cmd->options[i], (1 << io_class_opt_flag_required))) { - printed_ops++; - } - } - - print_options_usage(cmd->options, " ", io_class_print_param, - (1 << flag) | (1 << io_class_opt_flag_required)); - - if (all_ops != printed_ops) { - cas_printf(LOG_INFO, " [option...]"); - } command_name_in_brackets(option_name, MAX_STR_LEN, iter->short_name, iter->long_name); - cas_printf(LOG_INFO, "\nOptions that are valid with %s are:\n", option_name); - print_list_options(cmd->options, (1 << flag), io_class_print_param); + if (iter->priv & (1 << standby_opt_flag_set)) { + /* Option is set, check if this option is allowed */ + mask = (1 << standby_params.subcmd); + if (0 == (mask & iter->priv)) { + cas_printf(LOG_INFO, "Option '%s' is not allowed\n", option_name); + result = -1; + } - cas_printf(LOG_INFO, "\n"); + } else { + /* Option is missing, check if it is required for this sub-command*/ + mask = (1 << standby_params.subcmd) | (1 << standby_opt_flag_required); + if (mask == (iter->priv & mask)) { + cas_printf(LOG_INFO, "Option '%s' is missing\n", option_name); + result = -1; + } + } } + + return result; } -static int handle_help(); +/* Command handler */ +int standby_handle() { + /* Check if sub-command was specified */ + if (standby_opt_subcmd_unknown == standby_params.subcmd) { + cmd_subcmd_print_invalid_subcmd(standby_params_options); + return FAILURE; + } + + /* Check if all required options are set */ + if (standby_is_missing()) { + return FAILURE; + } + + switch (standby_params.subcmd) { + case standby_opt_subcmd_init: + return standby_init(standby_params.cache_id, + standby_params.line_size, + standby_params.cache_device, + standby_params.force); + case standby_opt_subcmd_load: + return standby_load(standby_params.cache_id, + standby_params.line_size, + standby_params.cache_device); + case standby_opt_subcmd_detach: + return standby_detach(standby_params.cache_id); + case standby_opt_subcmd_activate: + return standby_activate(standby_params.cache_id, + standby_params.cache_device); + } + + return FAILURE; +} + +void standby_help(app *app_values, cli_command *cmd) +{ + cmd_subcmd_help(app_values, cmd, standby_opt_flag_required); +} + +/******************************************************************************* + * Zero metadata command + ******************************************************************************/ struct { const char *device; @@ -1961,6 +2161,10 @@ int handle_zero() return zero_md(zero_params.device, zero_params.force); } +/******************************************************************************* + * Command properties + ******************************************************************************/ + static cli_command cas_commands[] = { { .name = "start-cache", @@ -2147,6 +2351,16 @@ static cli_command cas_commands[] = { .handle = handle_help, .help = NULL }, + { + .name = "standby", + .desc = "Manage failover standby", + .long_desc = NULL, + .options = standby_params_options, + .command_handle_opts = standby_handle_option, + .handle = standby_handle, + .flags = CLI_SU_REQUIRED, + .help = standby_help, + }, { .name = "zero-metadata", .desc = "Clear metadata from caching device", @@ -2157,30 +2371,6 @@ static cli_command cas_commands[] = { .flags = CLI_SU_REQUIRED, .help = NULL }, - { - .name = "failover-detach", - .desc = "Detach cache device from standby cache instance", - .long_desc = "Detach cache device from standby cache instance. " - "Cache continues to run in failover standby mode, " - "awaiting activation on a new drive.", - .options = failover_detach_options, - .command_handle_opts = command_handle_option, - .handle = handle_failover_detach, - .flags = CLI_SU_REQUIRED, - .help = NULL, - - }, - { - .name = "failover-activate", - .desc = "Activate standby cache instance", - .long_desc = NULL, - .options = failover_activate_options, - .command_handle_opts = command_handle_option, - .handle = handle_failover_activate, - .flags = CLI_SU_REQUIRED, - .help = NULL, - - }, { .name = "script", .options = script_params_options, diff --git a/casadm/extended_err_msg.c b/casadm/extended_err_msg.c index c2c6707..a1c82f4 100644 --- a/casadm/extended_err_msg.c +++ b/casadm/extended_err_msg.c @@ -179,8 +179,8 @@ struct { "Operation not permitted in failover standby mode" }, { - OCF_ERR_FAILOVER_ATTACHED, - "Cache device is attached, please detach it first with --failover-detach" + OCF_ERR_STANDBY_ATTACHED, + "Cache device is attached, please detach it first with --standby --detach" }, /* CAS kernel error mappings*/ diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 6d60e60..482b034 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -1891,7 +1891,8 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, case CACHE_INIT_LOAD: attach_cfg->open_cores = true; case CACHE_INIT_NEW: - case CACHE_INIT_STANDBY: + case CACHE_INIT_STANDBY_NEW: + case CACHE_INIT_STANDBY_LOAD: break; default: return -OCF_ERR_INVAL; @@ -2111,7 +2112,8 @@ static int _cache_start_finalize(ocf_cache_t cache, int init_mode, _cache_mngt_log_cache_device_path(cache, ctx->device_cfg); - if (activate || init_mode != CACHE_INIT_STANDBY) { + if (activate || (init_mode != CACHE_INIT_STANDBY_NEW && + init_mode != CACHE_INIT_STANDBY_LOAD)) { result = cas_cls_init(cache); if (result) { ctx->ocf_start_error = result; @@ -2137,7 +2139,8 @@ static int _cache_start_finalize(ocf_cache_t cache, int init_mode, ocf_core_visit(cache, _cache_mngt_core_device_loaded_visitor, NULL, false); break; - case CACHE_INIT_STANDBY: + case CACHE_INIT_STANDBY_NEW: + case CACHE_INIT_STANDBY_LOAD: result = cache_mngt_initialize_cache_exported_object(cache); if (result) { ctx->ocf_start_error = result; @@ -2181,7 +2184,7 @@ int cache_mngt_check_bdev(struct ocf_mngt_cache_device_config *device_cfg, return 0; } -int cache_mngt_failover_detach(struct kcas_failover_detach *cmd) +int cache_mngt_standby_detach(struct kcas_standby_detach *cmd) { ocf_cache_t cache; struct cache_priv *cache_priv; @@ -2222,7 +2225,7 @@ int cache_mngt_failover_detach(struct kcas_failover_detach *cmd) if (result) goto out_cache_put; - ocf_mngt_cache_failover_detach(cache, _cache_mngt_generic_complete, + ocf_mngt_cache_standby_detach(cache, _cache_mngt_generic_complete, &context); wait_for_completion(&context.cmpl); @@ -2235,8 +2238,29 @@ out_module_put: return result; } -int cache_mngt_activate(struct ocf_mngt_cache_device_config *cfg, - struct kcas_failover_activate *cmd) +int cache_mngt_prepare_cache_standby_activate_cfg( + struct ocf_mngt_cache_standby_activate_config *cfg, + struct kcas_standby_activate *cmd) +{ + int result; + + if (cmd->cache_id == OCF_CACHE_ID_INVALID) + return -OCF_ERR_INVAL; + + memset(cfg, 0, sizeof(*cfg)); + + result = cache_mngt_prepare_cache_device_cfg(&cfg->device, + cmd->cache_path); + if (result) + return result; + + cfg->open_cores = true; + + return 0; +} + +int cache_mngt_activate(struct ocf_mngt_cache_standby_activate_config *cfg, + struct kcas_standby_activate *cmd) { struct _cache_mngt_attach_context *context; ocf_cache_t cache; @@ -2263,7 +2287,7 @@ int cache_mngt_activate(struct ocf_mngt_cache_device_config *cfg, if (result) goto out_cache_put; - result = cache_mngt_check_bdev(cfg, false); + result = cache_mngt_check_bdev(&cfg->device, false); if (result) goto out_cache_unlock; @@ -2276,7 +2300,7 @@ int cache_mngt_activate(struct ocf_mngt_cache_device_config *cfg, /* TODO: doesn't this need to be copied to avoid use-after-free * in case where calle is interrupted and returns??? */ - context->device_cfg = cfg; + context->device_cfg = &cfg->device; context->cache = cache; cache_priv = ocf_cache_get_priv(cache); @@ -2290,7 +2314,7 @@ int cache_mngt_activate(struct ocf_mngt_cache_device_config *cfg, } _cache_mngt_async_context_init(&context->async); - ocf_mngt_cache_activate(cache, cfg, _cache_mngt_start_complete, + ocf_mngt_cache_standby_activate(cache, cfg, _cache_mngt_start_complete, context); result = wait_for_completion_interruptible(&context->async.cmpl); @@ -2336,11 +2360,16 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, return result; } - if (cmd->init_cache == CACHE_INIT_LOAD) + switch (cmd->init_cache) { + case CACHE_INIT_LOAD: + case CACHE_INIT_STANDBY_LOAD: result = _cache_mngt_check_metadata(cfg, cmd->cache_path_name); - if (result) { - module_put(THIS_MODULE); - return result; + if (result) { + module_put(THIS_MODULE); + return result; + } + default: + break; } context = kzalloc(sizeof(*context), GFP_KERNEL); @@ -2394,8 +2423,12 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, ocf_mngt_cache_load(cache, attach_cfg, _cache_mngt_start_complete, context); break; - case CACHE_INIT_STANDBY: - ocf_mngt_cache_standby(cache, attach_cfg, + case CACHE_INIT_STANDBY_NEW: + ocf_mngt_cache_standby_attach(cache, attach_cfg, + _cache_mngt_start_complete, context); + break; + case CACHE_INIT_STANDBY_LOAD: + ocf_mngt_cache_standby_load(cache, attach_cfg, _cache_mngt_start_complete, context); break; default: @@ -2932,7 +2965,7 @@ int cache_mngt_get_info(struct kcas_cache_info *info) if (result) goto unlock; - if (info->info.attached && !info->info.failover_detached) { + if (info->info.attached && !info->info.standby_detached) { uuid = ocf_cache_get_uuid(cache); BUG_ON(!uuid); strlcpy(info->cache_path_name, uuid->data, diff --git a/modules/cas_cache/layer_cache_management.h b/modules/cas_cache/layer_cache_management.h index 3311011..64c9d03 100644 --- a/modules/cas_cache/layer_cache_management.h +++ b/modules/cas_cache/layer_cache_management.h @@ -65,9 +65,6 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, struct ocf_mngt_cache_attach_config *attach_cfg, struct kcas_start_cache *cmd); -int cache_mngt_activate(struct ocf_mngt_cache_device_config *cfg, - struct kcas_failover_activate *cmd); - int cache_mngt_set_seq_cutoff_threshold(ocf_cache_t cache, ocf_core_t core, uint32_t thresh); @@ -114,9 +111,13 @@ int cache_mngt_set_cache_params(struct kcas_set_cache_param *info); int cache_mngt_get_cache_params(struct kcas_get_cache_param *info); -int cache_mngt_failover_detach(struct kcas_failover_detach *cmd); +int cache_mngt_standby_detach(struct kcas_standby_detach *cmd); -int cache_mngt_activate(struct ocf_mngt_cache_device_config *cfg, - struct kcas_failover_activate *cmd); +int cache_mngt_prepare_cache_standby_activate_cfg( + struct ocf_mngt_cache_standby_activate_config *cfg, + struct kcas_standby_activate *cmd); + +int cache_mngt_activate(struct ocf_mngt_cache_standby_activate_config *cfg, + struct kcas_standby_activate *cmd); #endif diff --git a/modules/cas_cache/service_ui_ioctl.c b/modules/cas_cache/service_ui_ioctl.c index 821f4f9..511d891 100644 --- a/modules/cas_cache/service_ui_ioctl.c +++ b/modules/cas_cache/service_ui_ioctl.c @@ -378,23 +378,23 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, RETURN_CMD_RESULT(cmd_info, arg, retval); } - case KCAS_IOCTL_FAILOVER_DETACH: { - struct kcas_failover_detach *cmd_info; + case KCAS_IOCTL_STANDBY_DETACH: { + struct kcas_standby_detach *cmd_info; GET_CMD_INFO(cmd_info, arg); - retval = cache_mngt_failover_detach(cmd_info); + retval = cache_mngt_standby_detach(cmd_info); RETURN_CMD_RESULT(cmd_info, arg, retval); } - case KCAS_IOCTL_FAILOVER_ACTIVATE: { - struct kcas_failover_activate *cmd_info; - struct ocf_mngt_cache_device_config cfg; + case KCAS_IOCTL_STANDBY_ACTIVATE: { + struct kcas_standby_activate *cmd_info; + struct ocf_mngt_cache_standby_activate_config cfg; GET_CMD_INFO(cmd_info, arg); - retval = cache_mngt_prepare_cache_device_cfg(&cfg, - cmd_info->cache_path); + retval = cache_mngt_prepare_cache_standby_activate_cfg(&cfg, + cmd_info); if (retval) RETURN_CMD_RESULT(cmd_info, arg, retval); diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index 0800c31..925ce10 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -36,7 +36,8 @@ #define CACHE_INIT_NEW 0 /**< initialize new metadata from fresh start */ #define CACHE_INIT_LOAD 1 /**< load existing metadata */ -#define CACHE_INIT_STANDBY 2 /**< initialize failover standby cache */ +#define CACHE_INIT_STANDBY_NEW 2 /**< initialize failover standby cache */ +#define CACHE_INIT_STANDBY_LOAD 3 /**< load failover standby cache */ struct kcas_start_cache { /** @@ -352,14 +353,14 @@ struct kcas_get_cache_param { int ext_err_code; }; -struct kcas_failover_detach +struct kcas_standby_detach { uint16_t cache_id; int ext_err_code; }; -struct kcas_failover_activate +struct kcas_standby_activate { uint16_t cache_id; char cache_path[MAX_STR_LEN]; /**< path to an ssd*/ @@ -498,10 +499,10 @@ struct kcas_failover_activate #define KCAS_IOCTL_REMOVE_INACTIVE _IOWR(KCAS_IOCTL_MAGIC, 37, struct kcas_remove_inactive) /** Detach caching drive from failover standby cache instance */ -#define KCAS_IOCTL_FAILOVER_DETACH _IOWR(KCAS_IOCTL_MAGIC, 38, struct kcas_failover_detach) +#define KCAS_IOCTL_STANDBY_DETACH _IOWR(KCAS_IOCTL_MAGIC, 38, struct kcas_standby_detach) -/** Activate standby failover cache instance */ -#define KCAS_IOCTL_FAILOVER_ACTIVATE _IOWR(KCAS_IOCTL_MAGIC, 39, struct kcas_failover_activate) +/** Activate failover standby cache instance */ +#define KCAS_IOCTL_STANDBY_ACTIVATE _IOWR(KCAS_IOCTL_MAGIC, 39, struct kcas_standby_activate) /** * Extended kernel CAS error codes diff --git a/ocf b/ocf index 4d4cdec..c664411 160000 --- a/ocf +++ b/ocf @@ -1 +1 @@ -Subproject commit 4d4cdece0d7321066236bb6e039670564aedef07 +Subproject commit c6644116ae53f7ba851473cda5c02423380ebcdf diff --git a/test/smoke_test/cas_ex.en.pws b/test/smoke_test/cas_ex.en.pws index b389e7a..37cfffe 100644 --- a/test/smoke_test/cas_ex.en.pws +++ b/test/smoke_test/cas_ex.en.pws @@ -34,6 +34,7 @@ config csv dev failover +init io kibibytes lru