Expose superblock operations as part of internal metadata API
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
parent
ab034ab53d
commit
9ab4c51dfa
@ -1617,102 +1617,6 @@ void ocf_metadata_error(struct ocf_cache *cache)
|
||||
cache->device->metadata_error = -1;
|
||||
}
|
||||
|
||||
struct ocf_metadata_read_sb_ctx;
|
||||
|
||||
typedef void (*ocf_metadata_read_sb_end_t)(
|
||||
struct ocf_metadata_read_sb_ctx *context);
|
||||
|
||||
struct ocf_metadata_read_sb_ctx {
|
||||
struct ocf_superblock_config superblock;
|
||||
ocf_metadata_read_sb_end_t cmpl;
|
||||
ocf_ctx_t ctx;
|
||||
void *priv1;
|
||||
void *priv2;
|
||||
int error;
|
||||
};
|
||||
|
||||
static void ocf_metadata_read_sb_complete(struct ocf_io *io, int error)
|
||||
{
|
||||
struct ocf_metadata_read_sb_ctx *context = io->priv1;
|
||||
ctx_data_t *data = ocf_io_get_data(io);
|
||||
|
||||
if (!error) {
|
||||
/* Read data from data into super block buffer */
|
||||
ctx_data_rd_check(context->ctx, &context->superblock, data,
|
||||
sizeof(context->superblock));
|
||||
}
|
||||
|
||||
ctx_data_free(context->ctx, data);
|
||||
ocf_io_put(io);
|
||||
|
||||
context->error = error;
|
||||
context->cmpl(context);
|
||||
|
||||
env_free(context);
|
||||
}
|
||||
|
||||
static int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume,
|
||||
ocf_metadata_read_sb_end_t cmpl, void *priv1, void *priv2)
|
||||
{
|
||||
struct ocf_metadata_read_sb_ctx *context;
|
||||
size_t sb_pages = BYTES_TO_PAGES(sizeof(context->superblock));
|
||||
ctx_data_t *data;
|
||||
struct ocf_io *io;
|
||||
int result = 0;
|
||||
|
||||
/* Allocate memory for first page of super block */
|
||||
context = env_zalloc(sizeof(*context), ENV_MEM_NORMAL);
|
||||
if (!context) {
|
||||
ocf_log(ctx, log_err, "Memory allocation error");
|
||||
return -OCF_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
context->cmpl = cmpl;
|
||||
context->ctx = ctx;
|
||||
context->priv1 = priv1;
|
||||
context->priv2 = priv2;
|
||||
|
||||
/* Allocate resources for IO */
|
||||
io = ocf_volume_new_io(volume, NULL, 0, sb_pages * PAGE_SIZE,
|
||||
OCF_READ, 0, 0);
|
||||
if (!io) {
|
||||
ocf_log(ctx, log_err, "Memory allocation error");
|
||||
result = -OCF_ERR_NO_MEM;
|
||||
goto err_io;
|
||||
}
|
||||
|
||||
data = ctx_data_alloc(ctx, sb_pages);
|
||||
if (!data) {
|
||||
ocf_log(ctx, log_err, "Memory allocation error");
|
||||
result = -OCF_ERR_NO_MEM;
|
||||
goto err_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read first page of cache device in order to recover metadata
|
||||
* properties
|
||||
*/
|
||||
result = ocf_io_set_data(io, data, 0);
|
||||
if (result) {
|
||||
ocf_log(ctx, log_err, "Metadata IO configuration error\n");
|
||||
result = -OCF_ERR_IO;
|
||||
goto err_set_data;
|
||||
}
|
||||
|
||||
ocf_io_set_cmpl(io, context, NULL, ocf_metadata_read_sb_complete);
|
||||
ocf_volume_submit_io(io);
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_data:
|
||||
ctx_data_free(ctx, data);
|
||||
err_data:
|
||||
ocf_io_put(io);
|
||||
err_io:
|
||||
env_free(context);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ocf_metadata_load_properties_cmpl(
|
||||
struct ocf_metadata_read_sb_ctx *context)
|
||||
{
|
||||
@ -1721,41 +1625,11 @@ static void ocf_metadata_load_properties_cmpl(
|
||||
ocf_metadata_load_properties_end_t cmpl = context->priv1;
|
||||
void *priv = context->priv2;
|
||||
ocf_ctx_t ctx = context->ctx;
|
||||
int result;
|
||||
|
||||
if (superblock->magic_number != CACHE_MAGIC_NUMBER) {
|
||||
ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n");
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_NO_METADATA, NULL);
|
||||
}
|
||||
|
||||
if (METADATA_VERSION() != superblock->metadata_version) {
|
||||
ocf_log(ctx, log_err, "Metadata version mismatch!\n");
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_METADATA_VER, NULL);
|
||||
}
|
||||
|
||||
if (!ocf_cache_line_size_is_valid(superblock->line_size)) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid cache line size!\n");
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL);
|
||||
}
|
||||
|
||||
if ((unsigned)superblock->metadata_layout >= ocf_metadata_layout_max) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid metadata layout!\n");
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL);
|
||||
}
|
||||
|
||||
if (superblock->cache_mode >= ocf_cache_mode_max) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid cache mode!\n");
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL);
|
||||
}
|
||||
|
||||
if (superblock->clean_shutdown > ocf_metadata_clean_shutdown) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid shutdown status!\n");
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL);
|
||||
}
|
||||
|
||||
if (superblock->dirty_flushed > DIRTY_FLUSHED) {
|
||||
ocf_log(ctx, log_err, "ERROR: Invalid flush status!\n");
|
||||
OCF_CMPL_RET(priv, -OCF_ERR_INVAL, NULL);
|
||||
}
|
||||
result = ocf_metadata_validate_superblock(ctx, superblock);
|
||||
if (result)
|
||||
OCF_CMPL_RET(priv, result, NULL);
|
||||
|
||||
properties.line_size = superblock->line_size;
|
||||
properties.layout = superblock->metadata_layout;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "metadata_superblock.h"
|
||||
#include "../ocf_priv.h"
|
||||
#include "../utils/utils_io.h"
|
||||
#include "../utils/utils_cache_line.h"
|
||||
|
||||
#define OCF_METADATA_SUPERBLOCK_DEBUG 0
|
||||
|
||||
@ -503,3 +504,170 @@ bool ocf_metadata_superblock_get_clean_shutdown(
|
||||
return sb->config->clean_shutdown;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct ocf_metadata_read_sb_ctx *context = io->priv1;
|
||||
ctx_data_t *data = ocf_io_get_data(io);
|
||||
|
||||
if (!error) {
|
||||
/* Read data from data into super block buffer */
|
||||
ctx_data_rd_check(context->ctx, &context->superblock, data,
|
||||
sizeof(context->superblock));
|
||||
}
|
||||
|
||||
ctx_data_free(context->ctx, data);
|
||||
ocf_io_put(io);
|
||||
|
||||
context->error = error;
|
||||
context->cmpl(context);
|
||||
|
||||
env_free(context);
|
||||
}
|
||||
|
||||
int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume,
|
||||
ocf_metadata_read_sb_end_t cmpl, void *priv1, void *priv2)
|
||||
{
|
||||
struct ocf_metadata_read_sb_ctx *context;
|
||||
size_t sb_pages = BYTES_TO_PAGES(sizeof(context->superblock));
|
||||
ctx_data_t *data;
|
||||
struct ocf_io *io;
|
||||
int result = 0;
|
||||
|
||||
/* Allocate memory for first page of super block */
|
||||
context = env_zalloc(sizeof(*context), ENV_MEM_NORMAL);
|
||||
if (!context) {
|
||||
ocf_log(ctx, log_err, "Memory allocation error");
|
||||
return -OCF_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
context->cmpl = cmpl;
|
||||
context->ctx = ctx;
|
||||
context->priv1 = priv1;
|
||||
context->priv2 = priv2;
|
||||
|
||||
/* Allocate resources for IO */
|
||||
io = ocf_volume_new_io(volume, NULL, 0, sb_pages * PAGE_SIZE,
|
||||
OCF_READ, 0, 0);
|
||||
if (!io) {
|
||||
ocf_log(ctx, log_err, "Memory allocation error");
|
||||
result = -OCF_ERR_NO_MEM;
|
||||
goto err_io;
|
||||
}
|
||||
|
||||
data = ctx_data_alloc(ctx, sb_pages);
|
||||
if (!data) {
|
||||
ocf_log(ctx, log_err, "Memory allocation error");
|
||||
result = -OCF_ERR_NO_MEM;
|
||||
goto err_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read first page of cache device in order to recover metadata
|
||||
* properties
|
||||
*/
|
||||
result = ocf_io_set_data(io, data, 0);
|
||||
if (result) {
|
||||
ocf_log(ctx, log_err, "Metadata IO configuration error\n");
|
||||
result = -OCF_ERR_IO;
|
||||
goto err_set_data;
|
||||
}
|
||||
|
||||
ocf_io_set_cmpl(io, context, NULL, ocf_metadata_read_sb_complete);
|
||||
ocf_volume_submit_io(io);
|
||||
|
||||
return 0;
|
||||
|
||||
err_set_data:
|
||||
ctx_data_free(ctx, data);
|
||||
err_data:
|
||||
ocf_io_put(io);
|
||||
err_io:
|
||||
env_free(context);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ocf_metadata_sb_crc_recovery_finish(ocf_pipeline_t pipeline,
|
||||
void *priv, int error)
|
||||
{
|
||||
struct ocf_metadata_context *context = priv;
|
||||
|
||||
context->cmpl(context->priv, error);
|
||||
ocf_pipeline_destroy(pipeline);
|
||||
}
|
||||
|
||||
struct ocf_pipeline_properties ocf_metadata_sb_crc_recovery_pipeline_props = {
|
||||
.priv_size = sizeof(struct ocf_metadata_context),
|
||||
.finish = ocf_metadata_sb_crc_recovery_finish,
|
||||
.steps = {
|
||||
OCF_PL_STEP(ocf_metadata_check_crc_sb_config),
|
||||
OCF_PL_STEP_FOREACH(ocf_metadata_check_crc,
|
||||
ocf_metadata_load_sb_check_crc_args),
|
||||
OCF_PL_STEP_TERMINATOR(),
|
||||
},
|
||||
};
|
||||
|
||||
void ocf_metadata_sb_crc_recovery(ocf_cache_t cache,
|
||||
ocf_metadata_end_t cmpl, void *priv)
|
||||
{
|
||||
struct ocf_metadata_context *context;
|
||||
ocf_pipeline_t pipeline;
|
||||
int result;
|
||||
|
||||
OCF_DEBUG_TRACE(cache);
|
||||
|
||||
result = ocf_pipeline_create(&pipeline, cache,
|
||||
&ocf_metadata_sb_crc_recovery_pipeline_props);
|
||||
if (result)
|
||||
OCF_CMPL_RET(priv, result);
|
||||
|
||||
context = ocf_pipeline_get_priv(pipeline);
|
||||
|
||||
context->cmpl = cmpl;
|
||||
context->priv = priv;
|
||||
context->pipeline = pipeline;
|
||||
context->cache = cache;
|
||||
context->ctrl = cache->metadata.priv;
|
||||
|
||||
ocf_pipeline_next(pipeline);
|
||||
}
|
||||
|
@ -97,4 +97,27 @@ void ocf_metadata_superblock_set_checksum(
|
||||
bool ocf_metadata_superblock_get_clean_shutdown(
|
||||
struct ocf_metadata_segment *self);
|
||||
|
||||
int ocf_metadata_validate_superblock(ocf_ctx_t ctx,
|
||||
struct ocf_superblock_config *superblock);
|
||||
|
||||
struct ocf_metadata_read_sb_ctx;
|
||||
|
||||
typedef void (*ocf_metadata_read_sb_end_t)(
|
||||
struct ocf_metadata_read_sb_ctx *context);
|
||||
|
||||
struct ocf_metadata_read_sb_ctx {
|
||||
struct ocf_superblock_config superblock;
|
||||
ocf_metadata_read_sb_end_t cmpl;
|
||||
ocf_ctx_t ctx;
|
||||
void *priv1;
|
||||
void *priv2;
|
||||
int error;
|
||||
};
|
||||
|
||||
int ocf_metadata_read_sb(ocf_ctx_t ctx, ocf_volume_t volume,
|
||||
ocf_metadata_read_sb_end_t cmpl, void *priv1, void *priv2);
|
||||
|
||||
void ocf_metadata_sb_crc_recovery(ocf_cache_t cache,
|
||||
ocf_metadata_end_t cmpl, void *priv);
|
||||
|
||||
#endif /* METADATA_SUPERBLOCK_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user