Redesign failover standby management
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
parent
4333f5f62c
commit
63bab9584c
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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*/
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
2
ocf
2
ocf
@ -1 +1 @@
|
||||
Subproject commit 4d4cdece0d7321066236bb6e039670564aedef07
|
||||
Subproject commit c6644116ae53f7ba851473cda5c02423380ebcdf
|
@ -34,6 +34,7 @@ config
|
||||
csv
|
||||
dev
|
||||
failover
|
||||
init
|
||||
io
|
||||
kibibytes
|
||||
lru
|
||||
|
Loading…
Reference in New Issue
Block a user