ocf/example/simple/src/ctx.c
Robert Baldyga aeca11a9c9
Merge pull request #577 from arutk/sample_fix
simple sample: offset handling fixes in data and volume
2021-11-30 15:01:30 +01:00

275 lines
5.4 KiB
C

/*
* Copyright(c) 2019-2021 Intel Corporation
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <execinfo.h>
#include <ocf/ocf.h>
#include "ocf_env.h"
#include "data.h"
#include "volume.h"
#include "ctx.h"
#define PAGE_SIZE 4096
/*
* Allocate structure representing data for io operations.
*/
ctx_data_t *ctx_data_alloc(uint32_t pages)
{
struct volume_data *data;
data = malloc(sizeof(*data));
data->ptr = malloc(pages * PAGE_SIZE);
data->offset = 0;
return data;
}
/*
* Free data structure.
*/
void ctx_data_free(ctx_data_t *ctx_data)
{
struct volume_data *data = ctx_data;
if (!data)
return;
free(data->ptr);
free(data);
}
/*
* This function is supposed to set protection of data pages against swapping.
* Can be non-implemented if not needed.
*/
static int ctx_data_mlock(ctx_data_t *ctx_data)
{
return 0;
}
/*
* Stop protecting data pages against swapping.
*/
static void ctx_data_munlock(ctx_data_t *ctx_data)
{
}
/*
* Read data into flat memory buffer.
*/
static uint32_t ctx_data_read(void *dst, ctx_data_t *src, uint32_t size)
{
struct volume_data *data = src;
memcpy(dst, data->ptr + data->offset, size);
data->offset += size;
return size;
}
/*
* Write data from flat memory buffer.
*/
static uint32_t ctx_data_write(ctx_data_t *dst, const void *src, uint32_t size)
{
struct volume_data *data = dst;
memcpy(data->ptr + data->offset, src, size);
data->offset += size;
return size;
}
/*
* Fill data with zeros.
*/
static uint32_t ctx_data_zero(ctx_data_t *dst, uint32_t size)
{
struct volume_data *data = dst;
memset(data->ptr + data->offset, 0, size);
data->offset += size;
return size;
}
/*
* Perform seek operation on data.
*/
static uint32_t ctx_data_seek(ctx_data_t *dst, ctx_data_seek_t seek,
uint32_t offset)
{
struct volume_data *data = dst;
switch (seek) {
case ctx_data_seek_begin:
data->offset = offset;
break;
case ctx_data_seek_current:
data->offset += offset;
break;
}
return offset;
}
/*
* Copy data from one structure to another.
*/
static uint64_t ctx_data_copy(ctx_data_t *dst, ctx_data_t *src,
uint64_t to, uint64_t from, uint64_t bytes)
{
struct volume_data *data_dst = dst;
struct volume_data *data_src = src;
memcpy(data_dst->ptr + to, data_src->ptr + from, bytes);
return bytes;
}
/*
* Perform secure erase of data (e.g. fill pages with zeros).
* Can be left non-implemented if not needed.
*/
static void ctx_data_secure_erase(ctx_data_t *ctx_data)
{
}
/*
* Initialize cleaner thread. Cleaner thread is left non-implemented,
* to keep this example as simple as possible.
*/
static int ctx_cleaner_init(ocf_cleaner_t c)
{
return 0;
}
/*
* Kick cleaner thread. Cleaner thread is left non-implemented,
* to keep this example as simple as possible.
*/
static void ctx_cleaner_kick(ocf_cleaner_t c)
{
}
/*
* Stop cleaner thread. Cleaner thread is left non-implemented, to keep
* this example as simple as possible.
*/
static void ctx_cleaner_stop(ocf_cleaner_t c)
{
}
/*
* Function prividing interface for printing to log used by OCF internals.
* It can handle differently messages at varous log levels.
*/
static int ctx_logger_print(ocf_logger_t logger, ocf_logger_lvl_t lvl,
const char *fmt, va_list args)
{
FILE *lfile = stdout;
if (lvl > log_info)
return 0;
if (lvl <= log_warn)
lfile = stderr;
return vfprintf(lfile, fmt, args);
}
#define CTX_LOG_TRACE_DEPTH 16
/*
* Function prividing interface for printing current stack. Used for debugging,
* and for providing additional information in log in case of errors.
*/
static int ctx_logger_dump_stack(ocf_logger_t logger)
{
void *trace[CTX_LOG_TRACE_DEPTH];
char **messages = NULL;
int i, size;
size = backtrace(trace, CTX_LOG_TRACE_DEPTH);
messages = backtrace_symbols(trace, size);
printf("[stack trace]>>>\n");
for (i = 0; i < size; ++i)
printf("%s\n", messages[i]);
printf("<<<[stack trace]\n");
free(messages);
return 0;
}
/*
* This structure describes context config, containing simple context info
* and pointers to ops callbacks. Ops are splitted into few categories:
* - data ops, providing context specific data handing interface,
* - cleaner ops, providing interface to start and stop clener thread,
* - metadata updater ops, providing interface for starting, stoping
* and kicking metadata updater thread.
* - logger ops, providing interface for text message logging
*/
static const struct ocf_ctx_config ctx_cfg = {
.name = "OCF Example",
.ops = {
.data = {
.alloc = ctx_data_alloc,
.free = ctx_data_free,
.mlock = ctx_data_mlock,
.munlock = ctx_data_munlock,
.read = ctx_data_read,
.write = ctx_data_write,
.zero = ctx_data_zero,
.seek = ctx_data_seek,
.copy = ctx_data_copy,
.secure_erase = ctx_data_secure_erase,
},
.cleaner = {
.init = ctx_cleaner_init,
.kick = ctx_cleaner_kick,
.stop = ctx_cleaner_stop,
},
.logger = {
.print = ctx_logger_print,
.dump_stack = ctx_logger_dump_stack,
},
},
};
/*
* Function initializing context. Prepares context, sets logger and
* registers volume type.
*/
int ctx_init(ocf_ctx_t *ctx)
{
int ret;
ret = ocf_ctx_create(ctx, &ctx_cfg);
if (ret)
return ret;
ret = volume_init(*ctx);
if (ret) {
ocf_ctx_put(*ctx);
return ret;
}
return 0;
}
/*
* Function cleaning up context. Unregisters volume type and
* deinitializes context.
*/
void ctx_cleanup(ocf_ctx_t ctx)
{
volume_cleanup(ctx);
ocf_ctx_put(ctx);
}