Explicitly validate superblock after load
Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com> Additional changes - load sb recovery CRC check Signed-off-by: Krzysztof Majzerowicz-Jaszcz <krzysztof.majzerowicz-jaszcz@intel.com>
This commit is contained in:
parent
90ff4afcda
commit
866bba72bf
@ -83,7 +83,7 @@
|
|||||||
/**
|
/**
|
||||||
* Maximum value of a valid core sequence number
|
* Maximum value of a valid core sequence number
|
||||||
*/
|
*/
|
||||||
#define OCF_SEQ_NO_MAX (65535UL)
|
#define OCF_SEQ_NO_MAX ((1ULL << (sizeof(ocf_core_id_t) * 8)) - 1)
|
||||||
/*
|
/*
|
||||||
* Invalid value of core sequence number
|
* Invalid value of core sequence number
|
||||||
*/
|
*/
|
||||||
|
@ -286,3 +286,10 @@ void ocf_engine_hndl_ops_req(struct ocf_request *req)
|
|||||||
|
|
||||||
ocf_engine_push_req_back(req, true);
|
ocf_engine_push_req_back(req, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode)
|
||||||
|
{
|
||||||
|
return ocf_cache_mode_is_valid((ocf_cache_mode_t)mode) &&
|
||||||
|
ocf_mngt_cache_mode_has_lazy_write(
|
||||||
|
(ocf_cache_mode_t)mode);
|
||||||
|
}
|
||||||
|
@ -52,17 +52,7 @@ static inline const char *ocf_get_io_iface_name(ocf_cache_mode_t cache_mode)
|
|||||||
return iface ? iface->name : "Unknown";
|
return iface ? iface->name : "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode)
|
bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode);
|
||||||
{
|
|
||||||
return mode >= ocf_cache_mode_wt && mode < ocf_cache_mode_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool ocf_req_cache_mode_has_lazy_write(ocf_req_cache_mode_t mode)
|
|
||||||
{
|
|
||||||
return ocf_cache_mode_is_valid((ocf_cache_mode_t)mode) &&
|
|
||||||
ocf_mngt_cache_mode_has_lazy_write(
|
|
||||||
(ocf_cache_mode_t)mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ocf_fallback_pt_is_on(ocf_cache_t cache);
|
bool ocf_fallback_pt_is_on(ocf_cache_t cache);
|
||||||
|
|
||||||
|
@ -1609,6 +1609,16 @@ void ocf_metadata_error(struct ocf_cache *cache)
|
|||||||
cache->device->metadata_error = -1;
|
cache->device->metadata_error = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (*ocf_metadata_read_sb_end_t)(
|
||||||
|
struct ocf_metadata_read_sb_ctx *context);
|
||||||
|
|
||||||
|
struct ocf_metadata_load_properties_ctx
|
||||||
|
{
|
||||||
|
ocf_cache_t cache;
|
||||||
|
ocf_metadata_load_properties_end_t cmpl;
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
static void ocf_metadata_load_properties_cmpl(
|
static void ocf_metadata_load_properties_cmpl(
|
||||||
struct ocf_metadata_read_sb_ctx *context)
|
struct ocf_metadata_read_sb_ctx *context)
|
||||||
{
|
{
|
||||||
|
@ -98,55 +98,115 @@ static void ocf_metadata_store_segment(ocf_pipeline_t pipeline,
|
|||||||
ocf_pipeline_next(pipeline);
|
ocf_pipeline_next(pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocf_metadata_check_crc_sb_config(ocf_pipeline_t pipeline,
|
|
||||||
void *priv, ocf_pipeline_arg_t arg)
|
#define ocf_log_invalid_superblock(param) \
|
||||||
|
ocf_log(ctx, log_err, \
|
||||||
|
"Loading %s: invalid %s\n", \
|
||||||
|
ocf_metadata_segment_names[ \
|
||||||
|
metadata_segment_sb_config], \
|
||||||
|
param);
|
||||||
|
|
||||||
|
|
||||||
|
int ocf_metadata_validate_superblock(ocf_ctx_t ctx,
|
||||||
|
struct ocf_superblock_config *superblock)
|
||||||
{
|
{
|
||||||
struct ocf_metadata_context *context = priv;
|
|
||||||
struct ocf_metadata_ctrl *ctrl;
|
|
||||||
struct ocf_superblock_config *sb_config;
|
|
||||||
ocf_cache_t cache = context->cache;
|
|
||||||
int segment = metadata_segment_sb_config;
|
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
|
|
||||||
ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv;
|
if (superblock->magic_number != CACHE_MAGIC_NUMBER) {
|
||||||
sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config);
|
ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n");
|
||||||
|
return -OCF_ERR_NO_METADATA;
|
||||||
crc = env_crc32(0, (void *)sb_config,
|
|
||||||
offsetof(struct ocf_superblock_config, checksum));
|
|
||||||
|
|
||||||
if (crc != sb_config->checksum[segment]) {
|
|
||||||
/* Checksum does not match */
|
|
||||||
ocf_cache_log(cache, log_err,
|
|
||||||
"Loading %s ERROR, invalid checksum\n",
|
|
||||||
ocf_metadata_segment_names[segment]);
|
|
||||||
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ocf_pipeline_next(pipeline);
|
if (METADATA_VERSION() != superblock->metadata_version) {
|
||||||
|
ocf_log(ctx, log_err, "Metadata version mismatch!\n");
|
||||||
|
return -OCF_ERR_METADATA_VER;
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = env_crc32(0, (void *)superblock,
|
||||||
|
offsetof(struct ocf_superblock_config, checksum));
|
||||||
|
|
||||||
|
if (crc != superblock->checksum[metadata_segment_sb_config]) {
|
||||||
|
ocf_log_invalid_superblock("checksum");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) {
|
||||||
|
ocf_log_invalid_superblock("shutdown status");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->dirty_flushed > DIRTY_FLUSHED) {
|
||||||
|
ocf_log_invalid_superblock("flush status");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->flapping_idx > 1) {
|
||||||
|
ocf_log_invalid_superblock("flapping index");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->cache_mode < 0 ||
|
||||||
|
superblock->cache_mode >= ocf_cache_mode_max) {
|
||||||
|
ocf_log_invalid_superblock("cache mode");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env_strnlen(superblock->name, sizeof(superblock->name)) >=
|
||||||
|
OCF_CACHE_NAME_SIZE) {
|
||||||
|
ocf_log_invalid_superblock("name");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->valid_parts_no > OCF_USER_IO_CLASS_MAX) {
|
||||||
|
ocf_log_invalid_superblock("partition count");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ocf_cache_line_size_is_valid(superblock->line_size)) {
|
||||||
|
ocf_log_invalid_superblock("cache line size");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) {
|
||||||
|
ocf_log_invalid_superblock("metadata layout");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->core_count > OCF_CORE_MAX) {
|
||||||
|
ocf_log_invalid_superblock("core count");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->cleaning_policy_type < 0 ||
|
||||||
|
superblock->cleaning_policy_type >= ocf_cleaning_max) {
|
||||||
|
ocf_log_invalid_superblock("cleaning policy");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superblock->promotion_policy_type < 0 ||
|
||||||
|
superblock->promotion_policy_type >=
|
||||||
|
ocf_promotion_max) {
|
||||||
|
ocf_log_invalid_superblock("promotion policy");
|
||||||
|
return -OCF_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocf_metadata_load_superblock_post(ocf_pipeline_t pipeline,
|
static void _ocf_metadata_validate_superblock(ocf_pipeline_t pipeline,
|
||||||
void *priv, ocf_pipeline_arg_t arg)
|
void *priv, ocf_pipeline_arg_t arg)
|
||||||
{
|
{
|
||||||
struct ocf_metadata_context *context = priv;
|
struct ocf_metadata_context *context = priv;
|
||||||
struct ocf_metadata_ctrl *ctrl;
|
struct ocf_metadata_ctrl *ctrl;
|
||||||
struct ocf_superblock_config *sb_config;
|
struct ocf_superblock_config *superblock;
|
||||||
ocf_cache_t cache = context->cache;
|
int ret;
|
||||||
|
|
||||||
ctrl = (struct ocf_metadata_ctrl *)cache->metadata.priv;
|
ctrl = (struct ocf_metadata_ctrl *)context->ctrl;
|
||||||
sb_config = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config);
|
superblock = METADATA_MEM_POOL(ctrl, metadata_segment_sb_config);
|
||||||
|
|
||||||
if (sb_config->core_count > OCF_CORE_MAX) {
|
ret = ocf_metadata_validate_superblock(context->cache->owner, superblock);
|
||||||
ocf_cache_log(cache, log_err,
|
if (ret)
|
||||||
"Loading cache state ERROR, invalid cores count\n");
|
OCF_PL_FINISH_RET(pipeline, ret);
|
||||||
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sb_config->valid_parts_no > OCF_USER_IO_CLASS_MAX) {
|
|
||||||
ocf_cache_log(cache, log_err,
|
|
||||||
"Loading cache state ERROR, invalid partition count\n");
|
|
||||||
OCF_PL_FINISH_RET(pipeline, -OCF_ERR_INVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ocf_pipeline_next(pipeline);
|
ocf_pipeline_next(pipeline);
|
||||||
}
|
}
|
||||||
@ -222,12 +282,11 @@ struct ocf_pipeline_properties ocf_metadata_load_sb_pipeline_props = {
|
|||||||
ocf_metadata_load_sb_store_segment_args),
|
ocf_metadata_load_sb_store_segment_args),
|
||||||
OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment,
|
OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment,
|
||||||
metadata_segment_sb_config),
|
metadata_segment_sb_config),
|
||||||
OCF_PL_STEP(ocf_metadata_check_crc_sb_config),
|
OCF_PL_STEP(_ocf_metadata_validate_superblock),
|
||||||
OCF_PL_STEP_FOREACH(ocf_metadata_load_segment,
|
OCF_PL_STEP_FOREACH(ocf_metadata_load_segment,
|
||||||
ocf_metadata_load_sb_load_segment_args),
|
ocf_metadata_load_sb_load_segment_args),
|
||||||
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
||||||
ocf_metadata_load_sb_load_segment_args),
|
ocf_metadata_load_sb_load_segment_args),
|
||||||
OCF_PL_STEP(ocf_metadata_load_superblock_post),
|
|
||||||
OCF_PL_STEP_TERMINATOR(),
|
OCF_PL_STEP_TERMINATOR(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -288,12 +347,11 @@ struct ocf_pipeline_properties ocf_metadata_load_sb_recov_pipeline_props = {
|
|||||||
ocf_metadata_load_sb_store_segment_args),
|
ocf_metadata_load_sb_store_segment_args),
|
||||||
OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment,
|
OCF_PL_STEP_ARG_INT(ocf_metadata_load_segment,
|
||||||
metadata_segment_sb_config),
|
metadata_segment_sb_config),
|
||||||
OCF_PL_STEP(ocf_metadata_check_crc_sb_config),
|
OCF_PL_STEP(_ocf_metadata_validate_superblock),
|
||||||
OCF_PL_STEP_FOREACH(ocf_metadata_load_segment,
|
OCF_PL_STEP_FOREACH(ocf_metadata_load_segment,
|
||||||
ocf_metadata_load_sb_recov_load_segment_args),
|
ocf_metadata_load_sb_recov_load_segment_args),
|
||||||
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
||||||
ocf_metadata_load_sb_recov_load_segment_args),
|
ocf_metadata_load_sb_recov_load_segment_args),
|
||||||
OCF_PL_STEP(ocf_metadata_load_superblock_post),
|
|
||||||
OCF_PL_STEP_TERMINATOR(),
|
OCF_PL_STEP_TERMINATOR(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -573,47 +631,6 @@ unsigned ocf_metadata_superblock_get_next_flapping_idx(
|
|||||||
return (sb->config->flapping_idx + 1) % 2;
|
return (sb->config->flapping_idx + 1) % 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ocf_metadata_validate_superblock(ocf_ctx_t ctx,
|
|
||||||
struct ocf_superblock_config *superblock)
|
|
||||||
{
|
|
||||||
if (superblock->magic_number != CACHE_MAGIC_NUMBER) {
|
|
||||||
ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n");
|
|
||||||
return -OCF_ERR_NO_METADATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (METADATA_VERSION() != superblock->metadata_version) {
|
|
||||||
ocf_log(ctx, log_err, "Metadata version mismatch!\n");
|
|
||||||
return -OCF_ERR_METADATA_VER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ocf_cache_line_size_is_valid(superblock->line_size)) {
|
|
||||||
ocf_log(ctx, log_err, "ERROR: Invalid cache line size!\n");
|
|
||||||
return -OCF_ERR_INVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) {
|
|
||||||
ocf_log(ctx, log_err, "ERROR: Invalid metadata layout!\n");
|
|
||||||
return -OCF_ERR_INVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (superblock->cache_mode >= ocf_cache_mode_max) {
|
|
||||||
ocf_log(ctx, log_err, "ERROR: Invalid cache mode!\n");
|
|
||||||
return -OCF_ERR_INVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) {
|
|
||||||
ocf_log(ctx, log_err, "ERROR: Invalid shutdown status!\n");
|
|
||||||
return -OCF_ERR_INVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (superblock->dirty_flushed > DIRTY_FLUSHED) {
|
|
||||||
ocf_log(ctx, log_err, "ERROR: Invalid flush status!\n");
|
|
||||||
return -OCF_ERR_INVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_metadata_read_sb_complete(struct ocf_io *io, int error)
|
static void ocf_metadata_read_sb_complete(struct ocf_io *io, int error)
|
||||||
{
|
{
|
||||||
struct ocf_metadata_read_sb_ctx *context = io->priv1;
|
struct ocf_metadata_read_sb_ctx *context = io->priv1;
|
||||||
|
@ -39,6 +39,11 @@ int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size)
|
|||||||
src, src_size);
|
src, src_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode)
|
||||||
|
{
|
||||||
|
return mode >= ocf_cache_mode_wt && mode < ocf_cache_mode_max;
|
||||||
|
}
|
||||||
|
|
||||||
const char *ocf_cache_get_name(ocf_cache_t cache)
|
const char *ocf_cache_get_name(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
OCF_CHECK_NULL(cache);
|
OCF_CHECK_NULL(cache);
|
||||||
|
@ -179,4 +179,6 @@ int ocf_cache_set_name(ocf_cache_t cache, const char *src, size_t src_size);
|
|||||||
|
|
||||||
int ocf_cache_volume_type_init(ocf_ctx_t ctx);
|
int ocf_cache_volume_type_init(ocf_ctx_t ctx);
|
||||||
|
|
||||||
|
bool ocf_cache_mode_is_valid(ocf_cache_mode_t mode);
|
||||||
|
|
||||||
#endif /* __OCF_CACHE_PRIV_H__ */
|
#endif /* __OCF_CACHE_PRIV_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user