ocf/src/utils/utils_pipeline.c
Amir Haroush 041df202b8 Fix alignment of private data in parallelize & pipeline
there is an issue when someone call to parallelize/pipeline
with some struct that is aligned (say to 64B)
but these APIs add their own data, right before
the user's private data.
so, the user's data is no longer aligned
which might cause segfault in some cases.

Signed-off-by: Amir Haroush <amir.haroush@huawei.com>
Signed-off-by: Shai Fultheim <shai.fultheim@huawei.com>
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
2023-04-17 20:35:38 +02:00

138 lines
3.1 KiB
C

/*
* Copyright(c) 2019-2022 Intel Corporation
* Copyright(c) 2023 Huawei Technologies
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ocf/ocf.h"
#include "../engine/cache_engine.h"
#include "../engine/engine_common.h"
#include "../ocf_request.h"
#include "utils_pipeline.h"
#define OCF_PIPELINE_ALIGNMENT 64
struct ocf_pipeline {
struct ocf_pipeline_properties *properties;
struct ocf_request *req;
int next_step;
int next_arg;
bool finish;
int error;
void *priv;
};
static int _ocf_pipeline_run_step(struct ocf_request *req)
{
ocf_pipeline_t pipeline = req->priv;
struct ocf_pipeline_step *step;
ocf_pipeline_arg_t arg;
if (pipeline->finish) {
pipeline->properties->finish(pipeline, pipeline->priv,
pipeline->error);
return 0;
}
while (true) {
step = &pipeline->properties->steps[pipeline->next_step];
switch (step->type) {
case ocf_pipeline_step_single:
pipeline->next_step++;
step->hndl(pipeline, pipeline->priv, &step->arg);
return 0;
case ocf_pipeline_step_conditional:
pipeline->next_step++;
if (step->pred(pipeline, pipeline->priv, &step->arg)) {
step->hndl(pipeline, pipeline->priv, &step->arg);
return 0;
}
continue;
case ocf_pipeline_step_foreach:
arg = &step->args[pipeline->next_arg++];
if (arg->type == ocf_pipeline_arg_terminator) {
pipeline->next_arg = 0;
pipeline->next_step++;
continue;
}
step->hndl(pipeline, pipeline->priv, arg);
return 0;
case ocf_pipeline_step_terminator:
pipeline->properties->finish(pipeline, pipeline->priv,
pipeline->error);
return 0;
default:
ENV_BUG();
}
}
return 0;
}
int ocf_pipeline_create(ocf_pipeline_t *pipeline, ocf_cache_t cache,
struct ocf_pipeline_properties *properties)
{
ocf_pipeline_t tmp_pipeline;
struct ocf_request *req;
tmp_pipeline = env_vzalloc(sizeof(*tmp_pipeline) +
properties->priv_size + OCF_PIPELINE_ALIGNMENT);
if (!tmp_pipeline)
return -OCF_ERR_NO_MEM;
if (properties->priv_size > 0) {
uintptr_t priv = (uintptr_t)tmp_pipeline + sizeof(*tmp_pipeline);
priv = OCF_DIV_ROUND_UP(priv, OCF_PIPELINE_ALIGNMENT) * OCF_PIPELINE_ALIGNMENT;
tmp_pipeline->priv = (void *)priv;
}
req = ocf_req_new(cache->mngt_queue, NULL, 0, 0, 0);
if (!req) {
env_vfree(tmp_pipeline);
return -OCF_ERR_NO_MEM;
}
tmp_pipeline->properties = properties;
tmp_pipeline->req = req;
tmp_pipeline->next_step = 0;
tmp_pipeline->finish = false;
tmp_pipeline->error = 0;
req->info.internal = true;
req->engine_handler = _ocf_pipeline_run_step;
req->priv = tmp_pipeline;
*pipeline = tmp_pipeline;
return 0;
}
void ocf_pipeline_destroy(ocf_pipeline_t pipeline)
{
ocf_req_put(pipeline->req);
env_vfree(pipeline);
}
void ocf_pipeline_set_priv(ocf_pipeline_t pipeline, void *priv)
{
pipeline->priv = priv;
}
void *ocf_pipeline_get_priv(ocf_pipeline_t pipeline)
{
return pipeline->priv;
}
void ocf_pipeline_next(ocf_pipeline_t pipeline)
{
ocf_engine_push_req_front(pipeline->req, false);
}
void ocf_pipeline_finish(ocf_pipeline_t pipeline, int error)
{
pipeline->finish = true;
pipeline->error = error;
ocf_engine_push_req_front(pipeline->req, false);
}