Remove upgrade-in-flight feature

Due to changes in Linux kernel this feature is not working anymore.

Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
Robert Baldyga 2021-08-11 20:33:16 +02:00
parent 5afc8af0e8
commit c968285d9f
24 changed files with 13 additions and 3336 deletions

View File

@ -56,7 +56,6 @@ OBJS += statistics_view.o
OBJS += statistics_view_raw_csv.o OBJS += statistics_view_raw_csv.o
OBJS += csvparse.o OBJS += csvparse.o
OBJS += extended_err_msg.o OBJS += extended_err_msg.o
OBJS += upgrade.o
OBJS += safeclib/memmove_s.o OBJS += safeclib/memmove_s.o
OBJS += safeclib/memcpy_s.o OBJS += safeclib/memcpy_s.o
OBJS += safeclib/memset_s.o OBJS += safeclib/memset_s.o

View File

@ -21,7 +21,6 @@
#include "cas_lib_utils.h" #include "cas_lib_utils.h"
#include "safeclib/safe_str_lib.h" #include "safeclib/safe_str_lib.h"
#include <cas_ioctl_codes.h> #include <cas_ioctl_codes.h>
#include "upgrade.h"
#include "statistics_view.h" #include "statistics_view.h"
#define HELP_HEADER OCF_PREFIX_LONG #define HELP_HEADER OCF_PREFIX_LONG
@ -1447,8 +1446,7 @@ enum {
script_cmd_min_id = 0, script_cmd_min_id = 0,
script_cmd_upgrade = script_cmd_min_id, script_cmd_check_cache_device = script_cmd_min_id,
script_cmd_check_cache_device,
script_cmd_add_core, script_cmd_add_core,
script_cmd_remove_core, script_cmd_remove_core,
@ -1478,14 +1476,6 @@ enum {
* script_opt_* .priv fields contains id of commands, where they can be used * script_opt_* .priv fields contains id of commands, where they can be used
*/ */
static cli_option script_params_options[] = { static cli_option script_params_options[] = {
[script_cmd_upgrade] = {
.short_name = 0,
.long_name = "upgrade-in-flight",
.args_count = 0,
.arg = NULL,
.priv = 0,
.flags = CLI_COMMAND_HIDDEN,
},
[script_cmd_check_cache_device] = { [script_cmd_check_cache_device] = {
.short_name = 0, .short_name = 0,
.long_name = "check-cache-device", .long_name = "check-cache-device",
@ -1696,8 +1686,6 @@ int script_handle() {
switch (command_args_values.script_subcmd) { switch (command_args_values.script_subcmd) {
case script_cmd_check_cache_device: case script_cmd_check_cache_device:
return check_cache_device(command_args_values.cache_device); return check_cache_device(command_args_values.cache_device);
case script_cmd_upgrade:
return upgrade_start();
case script_cmd_add_core: case script_cmd_add_core:
return add_core( return add_core(
command_args_values.cache_id, command_args_values.cache_id,

View File

@ -197,10 +197,6 @@ struct {
"Could not create exported object because file in /dev " "Could not create exported object because file in /dev "
"directory exists" "directory exists"
}, },
{
KCAS_ERR_IN_UPGRADE,
"Operation not allowed. CAS is in upgrade state"
},
{ {
KCAS_ERR_UNALIGNED, KCAS_ERR_UNALIGNED,
"Cache device logical sector size is greater than core device " "Cache device logical sector size is greater than core device "
@ -208,9 +204,6 @@ struct {
"on current cache device \nor try other device with the same " "on current cache device \nor try other device with the same "
"logical sector size as core device." "logical sector size as core device."
}, },
{
KCAS_ERR_NO_STORED_CONF,
"Internal kernel module error" },
{ {
KCAS_ERR_ROLLBACK, KCAS_ERR_ROLLBACK,
"Cannot restore previous configuration" "Cannot restore previous configuration"

View File

@ -1,40 +0,0 @@
/*
* Copyright(c) 2012-2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "cas_lib.h"
#include "cas_lib_utils.h"
#include <cas_ioctl_codes.h>
extern cas_printf_t cas_printf;
int upgrade_start()
{
int fd;
struct kcas_upgrade cmd_info;
if ((fd = open_ctrl_device()) == -1) {
return -1;
}
if (run_ioctl_interruptible_retry(fd, KCAS_IOCTL_UPGRADE, &cmd_info,
"Starting upgrade", 0, OCF_CORE_ID_INVALID) < 0) {
close(fd);
if (OCF_ERR_FLUSHING_INTERRUPTED == cmd_info.ext_err_code) {
return INTERRUPTED;
} else {
cas_printf(LOG_ERR, "Error starting upgrade\n");
print_err(cmd_info.ext_err_code);
return FAILURE;
}
}
close(fd);
return SUCCESS;
}

View File

@ -1,11 +0,0 @@
/*
* Copyright(c) 2012-2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef _UPGRADE_H
#define _UPGRADE_H
int upgrade_start();
#endif

View File

@ -12,7 +12,6 @@
#include <cas_ioctl_codes.h> #include <cas_ioctl_codes.h>
#include "linux_kernel_version.h" #include "linux_kernel_version.h"
#include "layer_upgrade.h"
#include "control.h" #include "control.h"
#include "layer_cache_management.h" #include "layer_cache_management.h"
#include "service_ui_ioctl.h" #include "service_ui_ioctl.h"
@ -21,6 +20,7 @@
#include "classifier.h" #include "classifier.h"
#include "context.h" #include "context.h"
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include "../cas_disk/cas_disk.h"
#define CAS_KERN_EMERG KERN_EMERG OCF_PREFIX_SHORT #define CAS_KERN_EMERG KERN_EMERG OCF_PREFIX_SHORT
#define CAS_KERN_ALERT KERN_ALERT OCF_PREFIX_SHORT #define CAS_KERN_ALERT KERN_ALERT OCF_PREFIX_SHORT
@ -76,7 +76,6 @@ struct casdsk_functions_mapper {
struct module *owner, struct casdsk_exp_obj_ops *ops); struct module *owner, struct casdsk_exp_obj_ops *ops);
void(*casdsk_exp_obj_free)(struct casdsk_disk *dsk); void(*casdsk_exp_obj_free)(struct casdsk_disk *dsk);
struct request_queue *(*casdsk_disk_get_queue)(struct casdsk_disk *dsk); struct request_queue *(*casdsk_disk_get_queue)(struct casdsk_disk *dsk);
void (*casdsk_store_config)(size_t n_blobs, struct casdsk_props_conf *blobs);
struct block_device *(*casdsk_disk_get_blkdev)(struct casdsk_disk *dsk); struct block_device *(*casdsk_disk_get_blkdev)(struct casdsk_disk *dsk);
struct request_queue *(*casdsk_exp_obj_get_queue)(struct casdsk_disk *dsk); struct request_queue *(*casdsk_exp_obj_get_queue)(struct casdsk_disk *dsk);
uint32_t (*casdsk_get_version)(void); uint32_t (*casdsk_get_version)(void);
@ -84,7 +83,6 @@ struct casdsk_functions_mapper {
struct casdsk_disk *(*casdsk_disk_claim)(const char *path, void *private); struct casdsk_disk *(*casdsk_disk_claim)(const char *path, void *private);
int (*casdsk_exp_obj_unlock)(struct casdsk_disk *dsk); int (*casdsk_exp_obj_unlock)(struct casdsk_disk *dsk);
int (*casdsk_disk_set_pt)(struct casdsk_disk *dsk); int (*casdsk_disk_set_pt)(struct casdsk_disk *dsk);
size_t (*casdsk_get_stored_config)(struct casdsk_props_conf **blobs);
struct gendisk *(*casdsk_disk_get_gendisk)(struct casdsk_disk *dsk); struct gendisk *(*casdsk_disk_get_gendisk)(struct casdsk_disk *dsk);
int (*casdsk_disk_attach) (struct casdsk_disk *dsk, struct module *owner, int (*casdsk_disk_attach) (struct casdsk_disk *dsk, struct module *owner,
struct casdsk_exp_obj_ops *ops); struct casdsk_exp_obj_ops *ops);
@ -92,7 +90,6 @@ struct casdsk_functions_mapper {
int (*casdsk_exp_obj_activate)(struct casdsk_disk *dsk); int (*casdsk_exp_obj_activate)(struct casdsk_disk *dsk);
bool (*casdsk_exp_obj_activated)(struct casdsk_disk *ds); bool (*casdsk_exp_obj_activated)(struct casdsk_disk *ds);
int (*casdsk_exp_obj_lock)(struct casdsk_disk *dsk); int (*casdsk_exp_obj_lock)(struct casdsk_disk *dsk);
void (*casdsk_free_stored_config)(void);
struct casdsk_disk *(*casdsk_disk_open)(const char *path, void *private); struct casdsk_disk *(*casdsk_disk_open)(const char *path, void *private);
int (*casdsk_disk_clear_pt)(struct casdsk_disk *dsk); int (*casdsk_disk_clear_pt)(struct casdsk_disk *dsk);
struct gendisk *(*casdsk_exp_obj_get_gendisk)(struct casdsk_disk *dsk); struct gendisk *(*casdsk_exp_obj_get_gendisk)(struct casdsk_disk *dsk);

View File

@ -1191,11 +1191,6 @@ int cache_mngt_prepare_core_cfg(struct ocf_mngt_core_config *cfg,
cfg->uuid.size = strnlen(cmd_info->core_path_name, MAX_STR_LEN) + 1; cfg->uuid.size = strnlen(cmd_info->core_path_name, MAX_STR_LEN) + 1;
cfg->try_add = cmd_info->try_add; cfg->try_add = cmd_info->try_add;
if (cas_upgrade_is_in_upgrade()) {
cfg->volume_type = BLOCK_DEVICE_VOLUME;
return 0;
}
if (!cas_bdev_exist(cfg->uuid.data)) if (!cas_bdev_exist(cfg->uuid.data))
return -OCF_ERR_INVAL_VOLUME_TYPE; return -OCF_ERR_INVAL_VOLUME_TYPE;
@ -2512,20 +2507,12 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush)
goto unlock; goto unlock;
} }
if (!cas_upgrade_is_in_upgrade()) { /* Destroy cache devices */
/* If we are not in upgrade - destroy cache devices */ status = block_dev_destroy_all_exported_objects(cache);
status = block_dev_destroy_all_exported_objects(cache); if (status != 0) {
if (status != 0) { printk(KERN_WARNING
printk(KERN_WARNING "Failed to remove all cached devices\n");
"Failed to remove all cached devices\n"); goto stop_thread;
goto stop_thread;
}
} else {
/*
* We are being switched to upgrade in flight mode -
* wait for finishing pending core requests
*/
cache_mngt_wait_for_rq_finish(cache);
} }
/* Flush cache again. This time we don't allow interruption. */ /* Flush cache again. This time we don't allow interruption. */

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +0,0 @@
/*
* Copyright(c) 2012-2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef __LAYER_UPGRADE_H
#define __LAYER_UPGRADE_H
#include "cas_cache/cas_cache.h"
extern bool in_upgrade;
/**
* @brief Check that CAS is in upgarde state
* @return true if is or false if isn't
*/
bool cas_upgrade_is_in_upgrade(void);
/**
* @brief Check that caches configuration is stored at casdsk
* @return 0 if exist
*/
int cas_upgrade_get_configuration(void);
/**
* @brief Start upgrade in flight procedure, dump configuration,
* switch caches to PT and close caches
* @return result
*/
int cas_upgrade(void);
/**
* @brief Finish upgrade in new CAS module - restore all caches
* @return result of restoring
*/
int cas_upgrade_finish(void);
/**
* @brief Try to parse configuration stored in casdisk
* @return result of verification
*/
int cas_upgrade_verify(void);
#endif /* __LAYER_UPGRADE_H */

View File

@ -21,10 +21,6 @@ MODULE_PARM_DESC(writeback_queue_unblock_size,
"Cache writeback queue size (60000) at which queue " "Cache writeback queue size (60000) at which queue "
"is unblocked when blocked"); "is unblocked when blocked");
u32 dry_run;
module_param(dry_run, uint, (S_IRUSR | S_IRGRP));
MODULE_PARM_DESC(dry_run, "Perform dry run on module load");
u32 use_io_scheduler = 1; u32 use_io_scheduler = 1;
module_param(use_io_scheduler, uint, (S_IRUSR | S_IRGRP)); module_param(use_io_scheduler, uint, (S_IRUSR | S_IRGRP));
MODULE_PARM_DESC(use_io_scheduler, MODULE_PARM_DESC(use_io_scheduler,
@ -47,7 +43,6 @@ MODULE_PARM_DESC(seq_cut_off_mb,
"Sequential cut off threshold in MiB. 0 - disable"); "Sequential cut off threshold in MiB. 0 - disable");
/* globals */ /* globals */
bool in_upgrade;
ocf_ctx_t cas_ctx; ocf_ctx_t cas_ctx;
struct casdsk_functions_mapper casdisk_functions; struct casdsk_functions_mapper casdisk_functions;
@ -94,7 +89,6 @@ int static cas_casdisk_lookup_funtions(void)
cas_lookup_symbol(casdsk_exp_obj_create); cas_lookup_symbol(casdsk_exp_obj_create);
cas_lookup_symbol(casdsk_exp_obj_free); cas_lookup_symbol(casdsk_exp_obj_free);
cas_lookup_symbol(casdsk_disk_get_queue); cas_lookup_symbol(casdsk_disk_get_queue);
cas_lookup_symbol(casdsk_store_config);
cas_lookup_symbol(casdsk_disk_get_blkdev); cas_lookup_symbol(casdsk_disk_get_blkdev);
cas_lookup_symbol(casdsk_exp_obj_get_queue); cas_lookup_symbol(casdsk_exp_obj_get_queue);
cas_lookup_symbol(casdsk_get_version); cas_lookup_symbol(casdsk_get_version);
@ -102,14 +96,12 @@ int static cas_casdisk_lookup_funtions(void)
cas_lookup_symbol(casdsk_disk_claim); cas_lookup_symbol(casdsk_disk_claim);
cas_lookup_symbol(casdsk_exp_obj_unlock); cas_lookup_symbol(casdsk_exp_obj_unlock);
cas_lookup_symbol(casdsk_disk_set_pt); cas_lookup_symbol(casdsk_disk_set_pt);
cas_lookup_symbol(casdsk_get_stored_config);
cas_lookup_symbol(casdsk_disk_get_gendisk); cas_lookup_symbol(casdsk_disk_get_gendisk);
cas_lookup_symbol(casdsk_disk_attach); cas_lookup_symbol(casdsk_disk_attach);
cas_lookup_symbol(casdsk_disk_set_attached); cas_lookup_symbol(casdsk_disk_set_attached);
cas_lookup_symbol(casdsk_exp_obj_activate); cas_lookup_symbol(casdsk_exp_obj_activate);
cas_lookup_symbol(casdsk_exp_obj_activated); cas_lookup_symbol(casdsk_exp_obj_activated);
cas_lookup_symbol(casdsk_exp_obj_lock); cas_lookup_symbol(casdsk_exp_obj_lock);
cas_lookup_symbol(casdsk_free_stored_config);
cas_lookup_symbol(casdsk_disk_open); cas_lookup_symbol(casdsk_disk_open);
cas_lookup_symbol(casdsk_disk_clear_pt); cas_lookup_symbol(casdsk_disk_clear_pt);
cas_lookup_symbol(casdsk_exp_obj_get_gendisk); cas_lookup_symbol(casdsk_exp_obj_get_gendisk);
@ -171,31 +163,6 @@ static int __init cas_init_module(void)
return result; return result;
} }
result = cas_upgrade_get_configuration();
if (-KCAS_ERR_NO_STORED_CONF == result) {
printk(KERN_INFO OCF_PREFIX_SHORT
"Not found configuration for upgrade. "
"Standard module initialization.\n");
} else {
if (!dry_run) {
result = cas_upgrade_finish();
if (result) {
printk(KERN_ERR OCF_PREFIX_SHORT
"Error during finish upgrade, "
"result: %d\n", result);
goto error_cas_ctx_init;
}
} else {
result = cas_upgrade_verify();
if (result) {
printk(KERN_ERR OCF_PREFIX_SHORT
"Error during upgrade "
"verification\n");
goto error_cas_ctx_init;
}
}
}
result = cas_ctrl_device_init(); result = cas_ctrl_device_init();
if (result) { if (result) {
printk(KERN_ERR OCF_PREFIX_SHORT printk(KERN_ERR OCF_PREFIX_SHORT

View File

@ -46,15 +46,6 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd,
return -EPERM; return -EPERM;
} }
if (cas_upgrade_is_in_upgrade() &&
cmd != KCAS_IOCTL_CACHE_INFO &&
cmd != KCAS_IOCTL_LIST_CACHE &&
cmd != KCAS_IOCTL_GET_CACHE_COUNT &&
cmd != KCAS_IOCTL_CORE_INFO &&
cmd != KCAS_IOCTL_PARTITION_INFO) {
return -EFAULT;
}
switch (cmd) { switch (cmd) {
case KCAS_IOCTL_START_CACHE: { case KCAS_IOCTL_START_CACHE: {
struct kcas_start_cache *cmd_info; struct kcas_start_cache *cmd_info;
@ -315,16 +306,6 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd,
RETURN_CMD_RESULT(cmd_info, arg, retval > 0 ? 0 : retval); RETURN_CMD_RESULT(cmd_info, arg, retval > 0 ? 0 : retval);
} }
case KCAS_IOCTL_UPGRADE: {
struct kcas_upgrade *cmd_info;
GET_CMD_INFO(cmd_info, arg);
retval = cas_upgrade();
RETURN_CMD_RESULT(cmd_info, arg, retval);
}
case KCAS_IOCTL_GET_CORE_POOL_COUNT: { case KCAS_IOCTL_GET_CORE_POOL_COUNT: {
struct kcas_core_pool_count *cmd_info; struct kcas_core_pool_count *cmd_info;

View File

@ -8,6 +8,5 @@
#define __CAS_UTILS_H__ #define __CAS_UTILS_H__
#include "utils_nvme.h" #include "utils_nvme.h"
#include "utils_properties.h"
#endif /* __CAS_UTILS_H__ */ #endif /* __CAS_UTILS_H__ */

View File

@ -56,9 +56,7 @@ struct {
{ KCAS_ERR_INV_IOCTL, EINVAL }, { KCAS_ERR_INV_IOCTL, EINVAL },
{ KCAS_ERR_DEV_PENDING, EBUSY }, { KCAS_ERR_DEV_PENDING, EBUSY },
{ KCAS_ERR_FILE_EXISTS, EEXIST }, { KCAS_ERR_FILE_EXISTS, EEXIST },
{ KCAS_ERR_IN_UPGRADE, EFAULT },
{ KCAS_ERR_UNALIGNED, EINVAL }, { KCAS_ERR_UNALIGNED, EINVAL },
{ KCAS_ERR_NO_STORED_CONF, EINTR },
{ KCAS_ERR_ROLLBACK, EFAULT }, { KCAS_ERR_ROLLBACK, EFAULT },
{ KCAS_ERR_NVME_BAD_FORMAT, EINVAL }, { KCAS_ERR_NVME_BAD_FORMAT, EINVAL },
{ KCAS_ERR_CONTAINS_PART, EINVAL }, { KCAS_ERR_CONTAINS_PART, EINVAL },

View File

@ -1,769 +0,0 @@
/*
* Copyright(c) 2012-2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#include "cas_cache.h"
#define INTERNAL_CALL 0
#define EXTERNAL_CALL 1
#define CAS_PROPERTIES_VERSION 101
#define VERSION_STR ".version"
/*
* Difference between constant and non constant entry is store in LSB
* e.g.:
* cas_property_string in binary 0000 1010
* cas_property_string_const in binary 0000 1011
*/
#define CAS_PROP_UNCONST(type) (type & ~CAS_PROPERTIES_CONST)
#define CAS_PROP_CHECK_CONST(type) (type & CAS_PROPERTIES_CONST)
enum cas_property_type {
cas_property_string = 10,
cas_property_string_const =
(cas_property_string | CAS_PROPERTIES_CONST),
cas_property_sint = 16,
cas_property_sint_const = (cas_property_sint | CAS_PROPERTIES_CONST),
cas_property_uint = 74,
cas_property_uint_const = (cas_property_uint | CAS_PROPERTIES_CONST),
};
struct cas_properties {
struct list_head list;
};
struct _cas_property {
uint8_t type;
char *key;
struct list_head item;
union {
void *value;
uint64_t value_uint;
int64_t value_sint;
};
};
struct cas_properties *cas_properties_create(void)
{
struct cas_properties *props;
int result;
props = kzalloc(sizeof(*props), GFP_KERNEL);
if (!props)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&props->list);
result = cas_properties_add_uint(props, VERSION_STR,
CAS_PROPERTIES_VERSION, CAS_PROPERTIES_CONST);
if (result) {
kfree(props);
return ERR_PTR(result);
}
result = cas_properties_add_uint(props, ".size", 0,
CAS_PROPERTIES_NON_CONST);
if (result) {
kfree(props);
return ERR_PTR(result);
}
return props;
}
void cas_properties_destroy(struct cas_properties *props)
{
struct list_head *curr, *tmp;
struct _cas_property *entry;
list_for_each_safe(curr, tmp, &props->list) {
entry = list_entry(curr, struct _cas_property, item);
list_del(curr);
if (cas_property_string == CAS_PROP_UNCONST(entry->type))
kfree(entry->value);
kfree(entry->key);
kfree(entry);
}
kfree(props);
}
static uint64_t _cas_prop_get_size(struct cas_properties *props)
{
struct list_head *curr;
struct _cas_property *entry;
uint64_t size_all = 0;
list_for_each(curr, &props->list) {
entry = list_entry(curr, struct _cas_property, item);
size_all += cas_prop_strnlen(entry->key, MAX_STRING_SIZE) + 1;
size_all += sizeof(entry->type);
switch (CAS_PROP_UNCONST(entry->type)) {
case cas_property_string:
size_all += cas_prop_strnlen(entry->value,
MAX_STRING_SIZE) + 1;
break;
case cas_property_sint:
size_all += sizeof(entry->value_sint);
break;
case cas_property_uint:
size_all += sizeof(entry->value_uint);
break;
default:
return 0;
}
}
return size_all;
}
static int _cas_prop_serialize_string(char *buffer, const uint64_t size,
uint64_t *offset, char *value)
{
uint64_t str_size = 0;
str_size = cas_prop_strnlen(value, MAX_STRING_SIZE) + 1;
if ((*offset + str_size) > size)
return -ENOMEM;
memcpy(buffer + *offset, value, str_size);
*offset += str_size;
return 0;
}
static int _cas_prop_parse_string(const char *buffer, const uint64_t size,
uint64_t *offset, char **str)
{
char *tmp_str = NULL;
uint64_t str_size = 0;
if (*offset >= size)
return -ENOMEM;
str_size = cas_prop_strnlen(&buffer[*offset], size - *offset ) + 1;
if (str_size > size - *offset) {
/* no null terminator at the end of buffer */
return -ENOMEM;
}
tmp_str = kstrdup(&buffer[*offset], GFP_KERNEL);
if (!tmp_str)
return -ENOMEM;
*offset += str_size;
*str = tmp_str;
return 0;
}
static int _cas_prop_serialize_int(char *buffer, const uint64_t size,
uint64_t *offset, uint64_t number)
{
int32_t i;
/*
* To prevent issue connected with byte order we
* serialize integer byte by byte.
*/
for (i = 0; i < sizeof(number); i++) {
char byte = number & 0xFF;
if (*offset < size)
buffer[*offset] = byte;
else
return -ENOMEM;
(*offset)++;
number = number >> 8;
}
return 0;
}
static int _cas_prop_serialize_uint(char *buffer, const uint64_t size,
uint64_t *offset, uint64_t number)
{
return _cas_prop_serialize_int(buffer, size, offset, number);
}
static int _cas_prop_serialize_sint(char *buffer, const uint64_t size,
uint64_t *offset, int64_t number)
{
return _cas_prop_serialize_int(buffer, size, offset, (uint64_t) number);
}
static int _cas_prop_parse_int(const char *buffer,
const uint64_t size, uint64_t *offset, uint64_t *number)
{
int32_t i;
uint64_t byte;
*number = 0;
/*
* To prevent issue connected with byte order we
* parse integer byte by byte.
*/
for (i = 0; i < sizeof(*number); i++) {
if (*offset >= size)
return -ENOMEM;
byte = buffer[*offset] & 0xFF;
byte = byte << (i * 8);
*number |= byte;
(*offset)++;
}
return 0;
}
static int _cas_prop_parse_uint(const char *buffer,
const uint64_t size, uint64_t *offset, uint64_t *number)
{
return _cas_prop_parse_int(buffer, size, offset, number);
}
static int _cas_prop_parse_sint(const char *buffer,
const uint64_t size, uint64_t *offset, int64_t *number)
{
return _cas_prop_parse_int(buffer, size, offset, (uint64_t *) number);
}
static int _cas_prop_serialize(struct _cas_property *entry, void *buffer,
const uint64_t size, uint64_t *offset)
{
uint64_t item_size = 0;
void *item;
int result = 0;
if (*offset > size)
return -ENOMEM;
/*
* Each entry is represented in buffer in order as below
* (e.g. in case we have entry with integer) :
* <----- entry ----->
* <- key -><-type-><- integer ->
* <- X bytes -><1 byte><- 8 byte ->
* | | | |
*/
/*
* First step - serialize key
*/
item_size = cas_prop_strnlen(entry->key, MAX_STRING_SIZE) + 1;
item = entry->key;
if ((*offset + item_size) > size)
return -ENOMEM;
memcpy(buffer + *offset, item, item_size);
*offset += item_size;
/*
* Second step - serialize type
*/
item_size = sizeof(entry->type);
item = &entry->type;
if ((*offset + item_size) > size)
return -ENOMEM;
memcpy(buffer + *offset, item, item_size);
*offset += item_size;
/*
* Third step - serialize value
*/
switch (CAS_PROP_UNCONST(entry->type)) {
case cas_property_string:
/* Serialize string */
result = _cas_prop_serialize_string(buffer, size, offset,
entry->value);
break;
case cas_property_sint:
/* Serialize signed integer */
result = _cas_prop_serialize_sint(buffer, size, offset,
entry->value_uint);
break;
case cas_property_uint:
/* Serialize unsigned integer */
result = _cas_prop_serialize_uint(buffer, size, offset,
entry->value_uint);
break;
default:
result = -EINVAL;
break;
}
return result;
}
int cas_properties_serialize(struct cas_properties *props,
struct casdsk_props_conf *caches_serialized_conf)
{
int result = 0;
uint64_t offset = 0, size;
uint16_t crc = 0;
void *buffer;
struct list_head *curr;
struct _cas_property *entry;
size = _cas_prop_get_size(props);
if (size == 0)
return -EINVAL;
buffer = vzalloc(size);
if (!buffer)
return -ENOMEM;
/*
* Update first entry on list - size of buffer
*/
result = cas_properties_add_uint(props, ".size", size,
CAS_PROPERTIES_CONST);
if (result)
goto error_after_buffer_allocation;
/*
* Serialize each entry, one by one
*/
list_for_each(curr, &props->list) {
entry = list_entry(curr, struct _cas_property, item);
result = _cas_prop_serialize(entry, buffer, size, &offset);
if (result)
goto error_after_buffer_allocation;
}
crc = crc16(0, buffer, size);
caches_serialized_conf->buffer = buffer;
caches_serialized_conf->size = size;
caches_serialized_conf->crc = crc;
return result;
error_after_buffer_allocation:
vfree(buffer);
return result;
}
void cas_properties_print(struct cas_properties *props)
{
struct list_head *curr;
struct _cas_property *entry;
char *abc;
/*
* Serialize each entry, one by one
*/
list_for_each(curr, &props->list) {
entry = list_entry(curr, struct _cas_property, item);
printk(KERN_DEBUG "[Upgrade] Key: %s", entry->key);
switch (CAS_PROP_UNCONST(entry->type)) {
case cas_property_string:
printk(", string, ");
abc = (char *)entry->value;
printk("Value: %s ", abc);
break;
case cas_property_sint:
break;
case cas_property_uint:
printk(", uint, ");
printk("Value: %llu ", entry->value_uint);
break;
default:
printk("Invalid type!");
break;
}
printk("\n");
}
}
static int _cas_prop_parse_version(const char *buffer, uint64_t *offset,
uint64_t *version, int trigger)
{
int result = 0;
char *key = NULL;
uint8_t type;
result = _cas_prop_parse_string(buffer, strlen(VERSION_STR) + 1,
offset, &key);
if (result)
goto error_during_parse_key;
if (strcmp(VERSION_STR, key)) {
result = -EINVAL;
goto error_after_parse_key;
}
type = buffer[*offset];
if (cas_property_uint_const != type) {
result = -EINVAL;
goto error_after_parse_key;
}
*offset += sizeof(type);
result = _cas_prop_parse_uint(buffer,
strlen(VERSION_STR) + 1 + sizeof(type) +
sizeof(*version), offset, version);
if (result)
goto error_after_parse_key;
/*
* In case that is external call
* we don't need check version.
*/
if (trigger == INTERNAL_CALL && *version != CAS_PROPERTIES_VERSION) {
printk(KERN_ERR "Version of interface using to parse is "
"different than version used to serialize\n");
result = -EPERM;
}
error_after_parse_key:
kfree(key);
error_during_parse_key:
return result;
}
int cas_properites_parse_version(struct casdsk_props_conf *caches_serialized_conf,
uint64_t *version)
{
uint64_t offset = 0;
char *buffer = NULL;
buffer = (char *) caches_serialized_conf->buffer;
if (!buffer)
return -EINVAL;
return _cas_prop_parse_version(buffer, &offset, version, EXTERNAL_CALL);
}
struct cas_properties *
cas_properites_parse(struct casdsk_props_conf *caches_serialized_conf)
{
struct cas_properties *props;
char *key = NULL, *value = NULL, *buffer = NULL;
int result;
uint8_t type;
uint64_t uint_value, size = 0, offset = 0, version = 0;
uint16_t crc;
int64_t sint_value;
bool constant = false;
props = cas_properties_create();
if (IS_ERR(props))
return ERR_PTR(-ENOMEM);
if (!caches_serialized_conf) {
result = -EINVAL;
goto error_after_props_allocation;
}
buffer = (char *) caches_serialized_conf->buffer;
if (!buffer) {
result = -EINVAL;
goto error_after_props_allocation;
}
size = caches_serialized_conf->size;
crc = crc16(0, buffer, size);
if (crc != caches_serialized_conf->crc) {
printk(KERN_ERR "Cache configuration corrupted");
result = -EINVAL;
goto error_after_props_allocation;
}
/*
* Parse first entry on list - version of interface used to
* serialization
*/
result = _cas_prop_parse_version(buffer, &offset, &version,
INTERNAL_CALL);
if (result)
goto error_after_props_allocation;
while (offset < size) {
/*
* Parse key of entry
*/
result = _cas_prop_parse_string(buffer, size, &offset, &key);
if (result)
goto error_after_props_allocation;
/*
* Parse type of entry
*/
if (offset + sizeof(type) > size) {
kfree(key);
goto error_after_props_allocation;
}
memcpy(&type, buffer + offset, sizeof(type));
offset += sizeof(type);
constant = CAS_PROP_CHECK_CONST(type);
type = CAS_PROP_UNCONST(type);
switch (type) {
case cas_property_string:
/* Parse string */
result = _cas_prop_parse_string(buffer, size, &offset,
&value);
if (result)
break;
/*
* Add new entry with string to CAS properties instance
*/
result |= cas_properties_add_string(props, key, value,
constant);
kfree(value);
break;
case cas_property_sint:
/* Parse signed integer */
result = _cas_prop_parse_sint(buffer, size, &offset,
&sint_value);
/* Add new entry with signed integer to CAS properties
* instance
*/
result |= cas_properties_add_sint(props, key,
sint_value, constant);
break;
case cas_property_uint:
/* Parse unsigned integer */
result = _cas_prop_parse_uint(buffer, size, &offset,
&uint_value);
/* Add new entry with unsigned integer to CAS properties
* instance
*/
result |= cas_properties_add_uint(props, key,
uint_value, constant);
break;
default:
result = -EINVAL;
break;
}
/*
* In case when we added new entry,
* we not need hold key value longer.
*/
kfree(key);
if (result)
goto error_after_props_allocation;
}
return props;
error_after_props_allocation:
cas_properties_destroy(props);
return ERR_PTR(result);
}
static struct _cas_property *_cas_prop_find(const struct cas_properties *props,
const char *key)
{
struct list_head *curr;
struct _cas_property *entry;
list_for_each(curr, &props->list) {
entry = list_entry(curr, struct _cas_property, item);
if (strncmp(key, entry->key, MAX_STRING_SIZE) == 0)
return entry;
}
return ERR_PTR(-ENOENT);
}
static struct _cas_property *_cas_prop_alloc_entry_key(const char *key)
{
struct _cas_property *entry;
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return ERR_PTR(-ENOMEM);
entry->key = kstrdup(key, GFP_KERNEL);
if (!entry->key) {
kfree(entry);
return ERR_PTR(-ENOMEM);
}
INIT_LIST_HEAD(&entry->item);
return entry;
}
/*
* ADD
*/
int cas_properties_add_uint(struct cas_properties *props, const char *key,
uint64_t value, bool constant)
{
struct _cas_property *entry;
/*
* Looks for entry with same key,
* if it is exist - update, if not - create new
*/
entry = _cas_prop_find(props, key);
if (IS_ERR(entry)) {
entry = _cas_prop_alloc_entry_key(key);
if (IS_ERR(entry))
return PTR_ERR(entry);
list_add_tail(&entry->item, &props->list);
} else if (cas_property_uint != entry->type) {
/*
* We can update only non constant entry,
* so we need compare type only with non constant type.
*/
return -EINVAL;
}
entry->type = constant ? cas_property_uint_const : cas_property_uint;
entry->value_uint = value;
return 0;
}
int cas_properties_add_sint(struct cas_properties *props, const char *key,
int64_t value, bool constant)
{
struct _cas_property *entry;
/*
* Looks for entry with same key,
* if it is exist - update, if not - create new
*/
entry = _cas_prop_find(props, key);
if (IS_ERR(entry)) {
entry = _cas_prop_alloc_entry_key(key);
if (IS_ERR(entry))
return PTR_ERR(entry);
list_add_tail(&entry->item, &props->list);
} else if (cas_property_sint != entry->type) {
/*
* We can update only non constant entry,
* so we need compare type only with non constant type.
*/
return -EINVAL;
}
entry->type = constant ? cas_property_sint_const : cas_property_sint;
entry->value_sint = value;
return 0;
}
int cas_properties_add_string(struct cas_properties *props, const char *key,
const char *value, bool constant)
{
struct _cas_property *entry;
char *tmp_value = NULL;
tmp_value = kstrdup(value, GFP_KERNEL);
if (!tmp_value)
return -ENOMEM;
/*
* Looks for entry with same key,
* if it is exist - update, if not - create new
*/
entry = _cas_prop_find(props, key);
if (IS_ERR(entry)) {
entry = _cas_prop_alloc_entry_key(key);
if (IS_ERR(entry)) {
kfree(tmp_value);
return PTR_ERR(entry);
}
list_add_tail(&entry->item, &props->list);
} else {
if (cas_property_string != entry->type) {
/*
* We can update only non constant entry,
* so we need compare type only with non constant type.
*/
kfree(tmp_value);
return -EINVAL;
}
kfree(entry->value);
}
entry->type = constant ? cas_property_string_const :
cas_property_string;
entry->value = tmp_value;
return 0;
}
/*
* GET
*/
int cas_properties_get_uint(struct cas_properties *props, const char *key,
uint64_t *value)
{
struct _cas_property *entry;
entry = _cas_prop_find(props, key);
if ((IS_ERR(entry) == 0) && (cas_property_uint ==
CAS_PROP_UNCONST(entry->type))) {
*value = entry->value_uint;
return 0;
}
return IS_ERR(entry) ? PTR_ERR(entry) : -EINVAL;
}
int cas_properties_get_sint(struct cas_properties *props, const char *key,
int64_t *value)
{
struct _cas_property *entry;
entry = _cas_prop_find(props, key);
if ((IS_ERR(entry) == 0) && (cas_property_sint ==
CAS_PROP_UNCONST(entry->type))) {
*value = entry->value_sint;
return 0;
}
return IS_ERR(entry) ? PTR_ERR(entry) : -EINVAL;
}
int cas_properties_get_string(struct cas_properties *props, const char *key,
char *value, uint32_t size)
{
struct _cas_property *entry;
entry = _cas_prop_find(props, key);
if ((IS_ERR(entry) == 0) && (cas_property_string ==
CAS_PROP_UNCONST(entry->type))) {
/* Check if size of destination memory is enough */
if (size < cas_prop_strnlen(entry->value, MAX_STRING_SIZE) + 1)
return -ENOMEM;
cas_prop_strncpy(value, size, entry->value,
cas_prop_strnlen(entry->value, MAX_STRING_SIZE));
return 0;
}
return IS_ERR(entry) ? PTR_ERR(entry) : -EINVAL;
}

View File

@ -1,153 +0,0 @@
/*
* Copyright(c) 2012-2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef UTILS_PROPERTIES_H_
#define UTILS_PROPERTIES_H_
#ifdef __KERNEL__
#define cas_prop_strncpy(dest, dest_size, src, src_size) \
strlcpy(dest, src, dest_size)
#define cas_prop_strnlen(string, size) strnlen(string, size)
#else
#define cas_prop_strncpy(dest, dest_size, src, src_size) \
strncpy(dest, src, src_size)
#define cas_prop_strnlen(string, size) strlen(string)
#endif
#include "../../cas_disk/cas_disk.h"
#define MAX_STRING_SIZE 4095
#define CAS_PROPERTIES_NON_CONST false
#define CAS_PROPERTIES_CONST true
/**
* @file utils_properties.h
* @brief CAS cache interface for collect and serialization CAS properties
*/
/**
* @brief Handler for instance of CAS properties
*/
struct cas_properties;
/**
* @brief Initialize instance of CAS properties
*
* @return Handler to instance of interface
*/
struct cas_properties *cas_properties_create(void);
/**
* @brief De-initialize instance of CAS properties
*
* @param props Handler to instance to de-initialize
*/
void cas_properties_destroy(struct cas_properties *props);
/**
* @brief Serialize given CAS properties instance to continuous buffer
*
* @param props instance of CAS properties
* @param idisk conf instance of CAS properties
* @return result of serialize CAS properties
*/
int cas_properties_serialize(struct cas_properties *props,
struct casdsk_props_conf *caches_serialized_conf);
/**
* @brief Parse of first entry given continuous buffer to get version of
* interface which been used to serialize
*
* @param buffer pointer to continuous buffer with serialized CAS properties
* @param version pointer to memory where we will put version
* @return result of getting version, 0 success
*/
int cas_properites_parse_version(struct casdsk_props_conf *caches_serialized_conf,
uint64_t *version);
/**
* @brief Parse of given continuous buffer to CAS properties instance
*
* @param buffer pointer to continuous buffer with serialized CAS properties
* @return handler to CAS properties instance
*/
struct cas_properties *
cas_properites_parse(struct casdsk_props_conf *caches_serialized_conf);
/**
* @brief Add unsigned integer to CAS properties instance
*
* @param props CAS properties instance to add variable
* @param key key paired with variable
* @param value value of variable
* @param private if true value cannot be updated
* @return result of adding 0 success
*/
int cas_properties_add_uint(struct cas_properties *props, const char *key,
uint64_t value, bool private);
/**
* @brief Add signed integer to CAS properties instance
*
* @param props CAS properties instance to add variable
* @param key key paired with variable
* @param value value of variable
* @param private if true value cannot be updated
* @return result of adding 0 success
*/
int cas_properties_add_sint(struct cas_properties *props, const char *key,
int64_t value, bool private);
/**
* @brief Add string to CAS properties instance
*
* @param props CAS properties instance to add variable
* @param key key paired with variable
* @param value value of variable
* @param private if true value cannot be updated
* @return result of adding 0 success
*/
int cas_properties_add_string(struct cas_properties *props, const char *key,
const char *value, bool private);
/**
* @brief Get unsigned integer to CAS properties instance
*
* @param props CAS properties instance to add variable
* @param key key paired with variable
* @param value pointer to memory where we will put value
* @return result of getting 0 success
*/
int cas_properties_get_uint(struct cas_properties *props, const char *key,
uint64_t *value);
/**
* @brief Get signed integer to CAS properties instance
*
* @param props CAS properties instance to add variable
* @param key key paired with variable
* @param value pointer to memory where we will put value
* @return result of getting 0 success
*/
int cas_properties_get_sint(struct cas_properties *props, const char *key,
int64_t *value);
/**
* @brief Get string integer to CAS properties instance
*
* @param props CAS properties instance to add variable
* @param key key paired with variable
* @param value pointer to memory where we will put value
* @param size size of destination memory
* @return result of getting 0 success, 1 error, 2 not enough space
* in destination
*/
int cas_properties_get_string(struct cas_properties *props, const char *key,
char *value, uint32_t size);
void cas_properties_print(struct cas_properties *props);
#endif /* UTILS_PROPERTIES_H_ */

View File

@ -33,13 +33,7 @@ int block_dev_open_object(ocf_volume_t vol, void *volume_params)
return 0; return 0;
} }
if (unlikely(true == cas_upgrade_is_in_upgrade())) { dsk = casdisk_functions.casdsk_disk_open(uuid->data, NULL);
dsk = casdisk_functions.casdsk_disk_claim(uuid->data, NULL);
casdisk_functions.casdsk_disk_set_attached(dsk);
} else {
dsk = casdisk_functions.casdsk_disk_open(uuid->data, NULL);
}
if (IS_ERR_OR_NULL(dsk)) { if (IS_ERR_OR_NULL(dsk)) {
int error = PTR_ERR(dsk) ?: -EINVAL; int error = PTR_ERR(dsk) ?: -EINVAL;
@ -62,12 +56,7 @@ void block_dev_close_object(ocf_volume_t vol)
if (bdobj->opened_by_bdev) if (bdobj->opened_by_bdev)
return; return;
if (likely(!cas_upgrade_is_in_upgrade())) { casdisk_functions.casdsk_disk_close(bdobj->dsk);
casdisk_functions.casdsk_disk_close(bdobj->dsk);
} else {
casdisk_functions.casdsk_disk_set_pt(bdobj->dsk);
casdisk_functions.casdsk_disk_detach(bdobj->dsk);
}
} }
unsigned int block_dev_get_max_io_size(ocf_volume_t vol) unsigned int block_dev_get_max_io_size(ocf_volume_t vol)

View File

@ -458,16 +458,10 @@ int block_dev_activate_exported_object(ocf_core_t core)
ocf_cache_t cache = ocf_core_get_cache(core); ocf_cache_t cache = ocf_core_get_cache(core);
struct bd_object *bvol = bd_object(obj); struct bd_object *bvol = bd_object(obj);
if (!cas_upgrade_is_in_upgrade()) { ret = casdisk_functions.casdsk_exp_obj_activate(bvol->dsk);
ret = casdisk_functions.casdsk_exp_obj_activate(bvol->dsk); if (ret) {
if (-EEXIST == ret) if (-EEXIST == ret)
ret = KCAS_ERR_FILE_EXISTS; ret = KCAS_ERR_FILE_EXISTS;
} else {
ret = casdisk_functions.casdsk_disk_attach(bvol->dsk, THIS_MODULE,
&_blockdev_exp_obj_ops);
}
if (ret) {
printk(KERN_ERR "Cannot activate exported object, %s.%s. " printk(KERN_ERR "Cannot activate exported object, %s.%s. "
"Error code %d\n", ocf_cache_get_name(cache), "Error code %d\n", ocf_cache_get_name(cache),
ocf_core_get_name(core), ret); ocf_core_get_name(core), ret);
@ -506,11 +500,6 @@ int block_dev_create_exported_object(ocf_core_t core)
goto end; goto end;
} }
if (cas_upgrade_is_in_upgrade()) {
bvol->expobj_valid = true;
return 0;
}
bvol->expobj_wq = alloc_workqueue("expobj_wq%s-%s", bvol->expobj_wq = alloc_workqueue("expobj_wq%s-%s",
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0, WQ_MEM_RECLAIM | WQ_HIGHPRI, 0,
get_cache_id_string(cache), get_cache_id_string(cache),

View File

@ -31,40 +31,12 @@ struct casdsk_exp_obj_ops {
struct bio *bio, void *private); struct bio *bio, void *private);
}; };
/**
* Stored configuration buffer description
*/
struct casdsk_props_conf {
void *buffer;
size_t size;
uint16_t crc;
};
/** /**
* @brief Get version of cas_disk interface * @brief Get version of cas_disk interface
* @return cas_disk interface version * @return cas_disk interface version
*/ */
uint32_t casdsk_get_version(void); uint32_t casdsk_get_version(void);
/**
* @brief Store configuration buffers in cas_disk
* @param n_blobs Number of configuration buffers
* @param blobs Array of configuration buffers structures
*/
void casdsk_store_config(size_t n_blobs, struct casdsk_props_conf *blobs);
/**
* @brief Get previously stored configuration buffers
* @param blobs Where to store pointer to configuration buffers array
* @return Number of stored configuration buffers
*/
size_t casdsk_get_stored_config(struct casdsk_props_conf **blobs);
/**
* @brief Free resources related to stored configuration buffers
*/
void casdsk_free_stored_config(void);
/** /**
* @brief Open block device * @brief Open block device
* @param path Path to block device * @param path Path to block device

View File

@ -12,11 +12,6 @@
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
struct casdsk_stored_config {
size_t n_blobs;
struct casdsk_props_conf *blobs;
};
struct casdsk_module { struct casdsk_module {
struct mutex lock; struct mutex lock;
@ -31,8 +26,6 @@ struct casdsk_module {
struct kmem_cache *pending_rqs_cache; struct kmem_cache *pending_rqs_cache;
struct kobject kobj; struct kobject kobj;
struct casdsk_stored_config config;
}; };
extern struct casdsk_module *casdsk_module; extern struct casdsk_module *casdsk_module;

View File

@ -20,9 +20,6 @@ MODULE_VERSION(CAS_VERSION);
static int iface_version = CASDSK_IFACE_VERSION; static int iface_version = CASDSK_IFACE_VERSION;
module_param(iface_version, int, (S_IRUSR | S_IRGRP)); module_param(iface_version, int, (S_IRUSR | S_IRGRP));
static int upgrade_in_progress = 0;
module_param(upgrade_in_progress, int, (S_IRUSR | S_IRGRP));
struct casdsk_module *casdsk_module; struct casdsk_module *casdsk_module;
uint32_t casdsk_get_version(void) uint32_t casdsk_get_version(void)
@ -31,46 +28,6 @@ uint32_t casdsk_get_version(void)
} }
EXPORT_SYMBOL(casdsk_get_version); EXPORT_SYMBOL(casdsk_get_version);
static void _casdsk_module_free_config(struct casdsk_module *mod)
{
int i;
if (mod->config.blobs) {
for (i = 0; i < mod->config.n_blobs; i++)
vfree(mod->config.blobs[i].buffer);
kfree(mod->config.blobs);
mod->config.blobs = NULL;
mod->config.n_blobs = 0;
}
}
void casdsk_store_config(size_t n_blobs, struct casdsk_props_conf *blobs)
{
upgrade_in_progress = 1;
_casdsk_module_free_config(casdsk_module);
casdsk_module->config.blobs = blobs;
casdsk_module->config.n_blobs = n_blobs;
}
EXPORT_SYMBOL(casdsk_store_config);
size_t casdsk_get_stored_config(struct casdsk_props_conf **blobs)
{
BUG_ON(!blobs);
*blobs = casdsk_module->config.blobs;
return casdsk_module->config.n_blobs;
}
EXPORT_SYMBOL(casdsk_get_stored_config);
void casdsk_free_stored_config(void)
{
CASDSK_DEBUG_TRACE();
_casdsk_module_free_config(casdsk_module);
upgrade_in_progress = 0;
}
EXPORT_SYMBOL(casdsk_free_stored_config);
static void _casdsk_module_release(struct kobject *kobj) static void _casdsk_module_release(struct kobject *kobj)
{ {
struct casdsk_module *mod; struct casdsk_module *mod;
@ -82,8 +39,6 @@ static void _casdsk_module_release(struct kobject *kobj)
mod = container_of(kobj, struct casdsk_module, kobj); mod = container_of(kobj, struct casdsk_module, kobj);
BUG_ON(!mod); BUG_ON(!mod);
_casdsk_module_free_config(mod);
kfree(mod); kfree(mod);
} }

View File

@ -290,10 +290,6 @@ struct kcas_capabilites {
int ext_err_code; int ext_err_code;
}; };
struct kcas_upgrade {
int ext_err_code;
};
/** /**
* Format NVMe namespace. * Format NVMe namespace.
*/ */
@ -404,7 +400,7 @@ struct kcas_get_cache_param {
* 16 * KCAS_IOCTL_GET_CACHE_COUNT * OK * * 16 * KCAS_IOCTL_GET_CACHE_COUNT * OK *
* 17 * KCAS_IOCTL_LIST_CACHE * OK * * 17 * KCAS_IOCTL_LIST_CACHE * OK *
* 18 * KCAS_IOCTL_GET_CAPABILITIES * DEPRECATED * * 18 * KCAS_IOCTL_GET_CAPABILITIES * DEPRECATED *
* 19 * KCAS_IOCTL_UPGRADE * OK * * 19 * KCAS_IOCTL_UPGRADE * DEPRACATED *
* 20 * KCAS_IOCTL_NVME_FORMAT * DEPRECATED * * 20 * KCAS_IOCTL_NVME_FORMAT * DEPRECATED *
* 21 * KCAS_IOCTL_START_CACHE * OK * * 21 * KCAS_IOCTL_START_CACHE * OK *
* 22 * KCAS_IOCTL_INSERT_CORE * OK * * 22 * KCAS_IOCTL_INSERT_CORE * OK *
@ -465,9 +461,6 @@ struct kcas_get_cache_param {
/** Provides capabilites of installed open cas module */ /** Provides capabilites of installed open cas module */
#define KCAS_IOCTL_GET_CAPABILITIES _IOWR(KCAS_IOCTL_MAGIC, 18, struct kcas_capabilites) #define KCAS_IOCTL_GET_CAPABILITIES _IOWR(KCAS_IOCTL_MAGIC, 18, struct kcas_capabilites)
/** Start upgrade in flight procedure */
#define KCAS_IOCTL_UPGRADE _IOR(KCAS_IOCTL_MAGIC, 19, struct kcas_upgrade)
/** Format NVMe namespace to support selected metadata mode */ /** Format NVMe namespace to support selected metadata mode */
#define KCAS_IOCTL_NVME_FORMAT _IOWR(KCAS_IOCTL_MAGIC, 20, struct kcas_nvme_format) #define KCAS_IOCTL_NVME_FORMAT _IOWR(KCAS_IOCTL_MAGIC, 20, struct kcas_nvme_format)
@ -551,16 +544,10 @@ enum kcas_error {
*/ */
KCAS_ERR_FILE_EXISTS, KCAS_ERR_FILE_EXISTS,
/** CAS is under upgrade */
KCAS_ERR_IN_UPGRADE,
/** Cache device sector size is greater than core device %s sector size /** Cache device sector size is greater than core device %s sector size
*/ */
KCAS_ERR_UNALIGNED, KCAS_ERR_UNALIGNED,
/** No caches configuration for upgrade in flight */
KCAS_ERR_NO_STORED_CONF,
/** Cannot roll-back previous configuration */ /** Cannot roll-back previous configuration */
KCAS_ERR_ROLLBACK, KCAS_ERR_ROLLBACK,

View File

@ -17,9 +17,6 @@ class CasVersion:
self.type = release_type self.type = release_type
self.base = f"{self.main}.{self.major}.{self.minor}" self.base = f"{self.main}.{self.major}.{self.minor}"
def can_be_upgraded(self):
return self.main >= 20
def __str__(self): def __str__(self):
return f"{self.main}.{self.major}.{self.minor}.{self.pr}" \ return f"{self.main}.{self.major}.{self.minor}.{self.pr}" \
f"{'.' + self.type if self.type is not None else ''}" f"{'.' + self.type if self.type is not None else ''}"
@ -46,7 +43,3 @@ def get_available_cas_versions():
versions = [CasVersion.from_git_tag(tag) for tag in release_tags] versions = [CasVersion.from_git_tag(tag) for tag in release_tags]
return versions return versions
def get_upgradable_cas_versions():
return [v for v in get_available_cas_versions() if v.can_be_upgraded()]

View File

@ -153,11 +153,6 @@ class casadm:
'--file', ioclass_file] '--file', ioclass_file]
return cls.run_cmd(cmd) return cls.run_cmd(cmd)
@classmethod
def start_upgrade(cls):
cmd = [cls.casadm_path, '--script', '--upgrade-in-flight']
return cls.run_cmd(cmd)
# Configuration file parser # Configuration file parser

View File

@ -1,426 +0,0 @@
#!/usr/bin/python3
#
# Copyright(c) 2019-2021 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause-Clear
#
import logging
import sys
import argparse
import subprocess
import os
from pathlib import Path
from shutil import copy
import opencas
from upgrade_utils import (
yn_prompt,
Failure,
Success,
Warn,
Abort,
StateMachine,
UpgradeState,
insert_module,
remove_module,
get_device_sysfs_path,
get_device_schedulers,
set_device_scheduler,
drop_os_caches,
)
LOG_FILE = "/var/log/opencas-upgrade/upgrade.log"
COMPILATION_LOG = "/var/log/opencas-upgrade/build.log"
INIT_CONFIG_FILE_TMP_PATH = "/tmp/opencas_upgrade_backup.conf"
CAS_CACHE_KEY = "CAS Cache Kernel Module"
CAS_DISK_KEY = "CAS Disk Kernel Module"
CAS_CLI_KEY = "CAS CLI Utility"
CAS_DISK_MIN_VER = 20
OCL_BUILD_ROOT = f"{os.path.dirname(__file__)}/.."
class InitUpgrade(UpgradeState):
log = "Performing initial checks"
will_prompt = True
class NotInstalled(Warn):
pass
def do_work(self):
if self.state_machine.params["force"]:
self.will_prompt = False
elif yn_prompt("Proceed with upgrade procedure?") == "n":
return Abort("User aborted")
try:
version = opencas.get_cas_version()
except FileNotFoundError:
return self.NotInstalled(f"Couldn't detect current CAS version")
except Exception as e:
return Failure(f"Failed to get current version of CAS {e}")
# Although there shouldn't be any problem with upgrade from CAS 19.9 to newer, this feature
# is not full validated so it is disabled by default.
if (int(version[CAS_DISK_KEY].split('.')[0]) < CAS_DISK_MIN_VER):
return Failure(f"Minimal cas_disk version required to perform upgrade is 20.01!")
if version[CAS_CLI_KEY] != version[CAS_CACHE_KEY]:
return Failure("Mismatch between CLI and cas_cache version")
active_devices = opencas.get_devices_state()
if any([device["status"] != "Running" for device in active_devices["caches"].values()]):
return Failure("Incomplete configuration. Run casadm -L to review CAS state!")
if len(active_devices["core_pool"]) != 0:
return Failure("Incomplete configuration. Run casadm -L to review CAS state!")
if os.path.isfile(opencas.cas_config.default_location):
try:
copy(opencas.cas_config.default_location, INIT_CONFIG_FILE_TMP_PATH)
except IOError:
return Failure("Could not save init config file backup")
else:
logging.info("Init config file not found")
return Success()
class BuildCas(UpgradeState):
log = "Compiling Open CAS"
def do_work(self):
with open(COMPILATION_LOG, "w") as build_log:
logging.info("Running ./configure for CAS")
p = subprocess.run(
["./configure"], cwd=OCL_BUILD_ROOT, stdout=build_log, stderr=build_log
)
if p.returncode:
return Failure(f"Configuration of Open CAS failed. Build log: {COMPILATION_LOG}")
logging.info("Compiling CAS")
p = subprocess.run(
["make", "-j"], cwd=OCL_BUILD_ROOT, stdout=build_log, stderr=build_log
)
if p.returncode:
return Failure(f"Compilation of Open CAS failed. Build log: {COMPILATION_LOG}")
return Success()
class RestoreInitConfig(UpgradeState):
log = "Restore original init config file"
def do_work(self):
if not os.path.isfile(INIT_CONFIG_FILE_TMP_PATH):
logging.warning("Init config backup file not found")
return Success()
try:
copy(INIT_CONFIG_FILE_TMP_PATH, opencas.cas_config.default_location)
except IOError:
logging.error(f"Failed to restore original init config file from "
f"{INIT_CONFIG_FILE_TMP_PATH}. Configuration has to be restored manually.")
return Failure()
os.remove(INIT_CONFIG_FILE_TMP_PATH)
return Success()
class InstallCas(UpgradeState):
log = "Installing new Open CAS files"
def do_work(self):
with open(COMPILATION_LOG, "a") as install_log:
p = subprocess.run(
["make", "install"], cwd=OCL_BUILD_ROOT, stdout=install_log, stderr=install_log
)
if p.returncode:
return Failure(
f"Installation of Open CAS failed. Installation log: {COMPILATION_LOG}"
)
return Success()
class InsertModule(UpgradeState):
module_path = f"{OCL_BUILD_ROOT}/modules/cas_cache/cas_cache.ko"
options = {"installed": False}
def do_work(self):
try:
insert_module(self.module_path, **self.options)
except Exception as e:
return Failure(f"Couldn't load module {self.module_path}. Reason: {e}")
return Success()
class InsertNewModule(InsertModule):
log = "Try to insert new caching module"
class DryRun(InsertModule):
log = "Perform dry run to check upgrade data integrity"
options = {"installed": False, "dry_run": 1}
def do_work(self):
result = super().do_work()
if not isinstance(result, Success):
return Failure("Dry run failed")
try:
logging.info(
"Insert with dry_run set succeeded. Removing module to attempt final insertion."
)
remove_module("cas_cache")
except Exception as e:
return Failure(f"Could not unload module. Reason: {e}")
return result
class InsertInstalledModule(InsertModule):
log = "Restore old cas_cache module"
module_path = "cas_cache"
options = {"installed": True}
class PrepareForUpgrade(UpgradeState):
log = "Preparing Open CAS for upgrade"
def do_work(self):
try:
logging.info("Switching CAS to upgrade mode")
opencas.casadm.start_upgrade()
except opencas.casadm.CasadmError as e:
return Failure(e)
return Success()
class RemoveModule(UpgradeState):
log = "Removing cas_cache module"
def do_work(self):
try:
logging.info("Removing cas_cache module")
remove_module("cas_cache")
except Exception as e:
return Failure(f"Failed to remove cas_cache module. Reason: {e}")
return Success()
class SetSchedulersToNoop(UpgradeState):
log = "Setting core devices schedulers to noop"
def do_work(self):
unique_core_sysfs_devices = {
get_device_sysfs_path(core["device"])
for core in opencas.get_devices_state()["cores"].values()
}
self.state_machine.schedulers = {}
for core_sysfs_path in unique_core_sysfs_devices:
current, available = get_device_schedulers(core_sysfs_path)
self.state_machine.schedulers[core_sysfs_path] = current
if current in ["noop", "none"]:
logging.info(f"Core {core_sysfs_path} already uses {current} scheduler. Skipping.")
elif "noop" in available:
logging.info(f"Switching scheduler for {core_sysfs_path}: {current} => noop")
set_device_scheduler(core_sysfs_path, "noop")
elif "none" in available:
logging.info(f"Switching scheduler for {core_sysfs_path}: {current} => none")
set_device_scheduler(core_sysfs_path, "none")
else:
logging.info(f"No appropriate scheduler available for {core_sysfs_path}. Skipping.")
return Success()
class RestoreCoreSchedulers(UpgradeState):
log = "Restoring core devices schedulers"
def do_work(self):
for core_sysfs_path, scheduler in self.state_machine.schedulers.items():
current = get_device_schedulers(core_sysfs_path)[0]
if scheduler in ["noop", "none"]:
logging.info(
f"Device {core_sysfs_path} already uses {scheduler} scheduler. Skipping."
)
else:
logging.info(f"Switching scheduler for {core_sysfs_path}: {current} => {scheduler}")
set_device_scheduler(core_sysfs_path, scheduler)
return Success()
class DropCaches(UpgradeState):
log = "Drop OS caches to ensure memory availability"
def do_work(self):
logging.info("Dropping slab and page caches using procfs")
drop_os_caches()
return Success()
class InstallStateMachine(StateMachine):
transition_map = {
BuildCas: {Success: InstallCas},
InstallCas: {"default": None},
"default": None,
}
class RegularInstall(UpgradeState):
log = "Installing Open CAS"
will_prompt = True
def do_work(self):
if (
yn_prompt("Previous CAS installation not detected. Perform regular installation?")
== "n"
):
return Abort("User aborted")
sm = InstallStateMachine(BuildCas)
result = sm.run()
return result
class UpgradeStateMachine(StateMachine):
"""
This class implements whole CAS in-flight upgrade procedure.
+-------------+ not +---------------+
|InitUpgrade +----------->+RegularInstall |
+------+------+ installed | |
| | +---------+ |
v | |BuildCas | |
+------+------+ fail | +---+-----+ |
|BuildCas +------+ | | |
+------+------+ | | v |
| | | +---+-----+ |
v | | |Install | |
+------+------+ fail | | +---------+ |
|SetToNoop +------+ | |
+------+------+ | +----------+----+
| | |
v +----------------+
+------+------+ fail |
|PrepareForUpg+-------------------+ |
+------+------+ | |
| | |
v | |
+------+------+ fail | |
|RemoveModule +-------------------+ |
+------+------+ | |
| | |
v | |
+------+------+ fail | |
|DropCaches +-------------------+ |
+------+------+ | |
| | |
v | |
+------+------+ fail | |
|DryRun +--------+ | |
+------+------+ | | |
| | | |
v | | |
+------+------+ fail | | |
|InsertNew +--------+ | |
+------+------+ | | |
| | | |
v | | |
+------+------+ fail | | |
|InstallCas +--------+ | |
+------+------+ v | |
| +------+--------+ | |
| |InsertInstalled| | |
v +------+--------+ | |
+------+------+ | | |
|RestoreConfig+<-------+ | |
+------+------+ | |
| | |
v | |
+------+------+ | |
|RestoreSched +<------------------+ |
+------+------+ v
| +------+---+
+---------------------->+ END |
+----------+
"""
transition_map = {
InitUpgrade: {Success: BuildCas, InitUpgrade.NotInstalled: RegularInstall},
RegularInstall: {"default": None},
BuildCas: {Success: SetSchedulersToNoop},
SetSchedulersToNoop: {Success: PrepareForUpgrade},
PrepareForUpgrade: {Success: RemoveModule, Failure: RestoreCoreSchedulers},
RemoveModule: {Success: DropCaches, Failure: RestoreCoreSchedulers},
DropCaches: {Success: DryRun, Failure: RestoreCoreSchedulers},
DryRun: {Success: InsertNewModule, Failure: InsertInstalledModule},
InsertNewModule: {Success: InstallCas, Failure: InsertInstalledModule},
InstallCas: {Success: RestoreInitConfig, Failure: InsertInstalledModule},
InsertInstalledModule: {"default": RestoreInitConfig},
RestoreInitConfig: {"default": RestoreCoreSchedulers},
RestoreCoreSchedulers: {"default": None},
"default": None,
}
def start(args):
logging.info(">>> Starting OpenCAS upgrade procedure")
s = UpgradeStateMachine(InitUpgrade, force=args.force)
result = s.run()
if not isinstance(result, Success):
print(f"Upgrade failed. Reason: {result}")
exit_code = 1
else:
print("Upgrade completed successfully!")
exit_code = 0
print(f"Full upgrade log: {LOG_FILE}")
return exit_code
def main():
Path(LOG_FILE).parent.mkdir(mode=0o700, parents=True, exist_ok=True)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)-5.5s] %(message)s",
handlers=[logging.FileHandler(LOG_FILE)],
)
parser = argparse.ArgumentParser(prog=__file__)
subparsers = parser.add_subparsers(title="actions")
parser_start = subparsers.add_parser(
"start", help="Upgrade Open CAS in flight to current version"
)
parser_start.add_argument("--force", action="store_true", help="Skip prompts")
parser_start.set_defaults(func=start)
if len(sys.argv[1:]) == 0:
parser.print_help()
return 1
else:
args = parser.parse_args(sys.argv[1:])
return args.func(args)
if __name__ == "__main__":
sys.exit(main())