
Resetting cache_error/core_error in ocf_req_forward_* functions may lead to overwriting already reported error if the forward is being done in the loop. To avoid this potential problem, introduce set of forward init functions intended to be called before the entire forward operation, which resets the error code and sets a forward callback. Signed-off-by: Robert Baldyga <robert.baldyga@huawei.com>
163 lines
3.9 KiB
C
163 lines
3.9 KiB
C
/*
|
|
* Copyright(c) 2024 Huawei Technologies
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "ocf/ocf.h"
|
|
#include "engine_io.h"
|
|
#include "engine_common.h"
|
|
#include "../ocf_priv.h"
|
|
#include "../ocf_cache_priv.h"
|
|
#include "../ocf_volume_priv.h"
|
|
#include "../ocf_request.h"
|
|
#include "../utils/utils_cache_line.h"
|
|
|
|
void ocf_engine_forward_cache_io(struct ocf_request *req, int dir,
|
|
uint64_t offset, uint64_t size, ocf_req_end_t callback)
|
|
{
|
|
ocf_cache_t cache = req->cache;
|
|
uint32_t seek = req->addr % ocf_line_size(cache);
|
|
uint32_t first_cl = ocf_bytes_2_lines(cache, offset + seek);
|
|
uint64_t addr;
|
|
|
|
ocf_req_forward_cache_init(req, callback);
|
|
|
|
addr = cache->device->metadata_offset;
|
|
addr += req->map[first_cl].coll_idx * ocf_line_size(cache);
|
|
addr += (offset + seek) % ocf_line_size(cache);
|
|
|
|
ocf_core_stats_cache_block_update(req->core, req->part_id,
|
|
dir, req->bytes);
|
|
|
|
ocf_req_forward_cache_io(req, dir, addr, size,
|
|
req->offset + offset);
|
|
}
|
|
|
|
void ocf_engine_forward_cache_io_req(struct ocf_request *req, int dir,
|
|
ocf_req_end_t callback)
|
|
{
|
|
ocf_cache_t cache = req->cache;
|
|
uint64_t addr, bytes, total_bytes = 0, addr_next = 0;
|
|
uint32_t i;
|
|
|
|
ocf_req_forward_cache_init(req, callback);
|
|
|
|
if (ocf_engine_is_sequential(req)) {
|
|
addr = cache->device->metadata_offset;
|
|
addr += req->map[0].coll_idx * ocf_line_size(cache);
|
|
addr += req->addr % ocf_line_size(cache);
|
|
|
|
ocf_core_stats_cache_block_update(req->core, req->part_id,
|
|
dir, req->bytes);
|
|
|
|
ocf_req_forward_cache_io(req, dir, addr, req->bytes,
|
|
req->offset);
|
|
return;
|
|
}
|
|
|
|
ocf_req_forward_cache_get(req);
|
|
for (i = 0; i < req->core_line_count; i++) {
|
|
if (addr_next) {
|
|
addr = addr_next;
|
|
} else {
|
|
addr = req->map[i].coll_idx;
|
|
addr *= ocf_line_size(cache);
|
|
addr += cache->device->metadata_offset;
|
|
}
|
|
bytes = ocf_line_size(cache);
|
|
|
|
if (i == 0) {
|
|
uint64_t seek = (req->addr) %
|
|
ocf_line_size(cache);
|
|
|
|
addr += seek;
|
|
bytes -= seek;
|
|
}
|
|
|
|
for (; i < (req->core_line_count - 1); i++) {
|
|
addr_next = req->map[i + 1].coll_idx;
|
|
addr_next *= ocf_line_size(cache);
|
|
addr_next += cache->device->metadata_offset;
|
|
|
|
if (addr_next != (addr + bytes))
|
|
break;
|
|
|
|
bytes += ocf_line_size(cache);
|
|
}
|
|
|
|
if (i == (req->core_line_count - 1)) {
|
|
uint64_t skip = (ocf_line_size(cache) -
|
|
((req->addr + req->bytes) %
|
|
ocf_line_size(cache))) % ocf_line_size(cache);
|
|
|
|
bytes -= skip;
|
|
}
|
|
|
|
bytes = OCF_MIN(bytes, req->bytes - total_bytes);
|
|
ENV_BUG_ON(bytes == 0);
|
|
|
|
ocf_core_stats_cache_block_update(req->core, req->part_id,
|
|
dir, bytes);
|
|
|
|
ocf_req_forward_cache_io(req, dir, addr, bytes,
|
|
req->offset + total_bytes);
|
|
|
|
total_bytes += bytes;
|
|
}
|
|
|
|
ENV_BUG_ON(total_bytes != req->bytes);
|
|
|
|
ocf_req_forward_cache_put(req);
|
|
}
|
|
|
|
void ocf_engine_forward_cache_flush_req(struct ocf_request *req,
|
|
ocf_req_end_t callback)
|
|
{
|
|
ocf_req_forward_cache_init(req, callback);
|
|
|
|
ocf_req_forward_cache_flush(req);
|
|
}
|
|
|
|
void ocf_engine_forward_cache_discard_req(struct ocf_request *req,
|
|
ocf_req_end_t callback)
|
|
{
|
|
ocf_req_forward_cache_init(req, callback);
|
|
|
|
ocf_req_forward_cache_discard(req, req->addr,
|
|
req->bytes);
|
|
}
|
|
|
|
void ocf_engine_forward_core_io_req(struct ocf_request *req,
|
|
ocf_req_end_t callback)
|
|
{
|
|
ocf_core_stats_core_block_update(req->core, req->part_id, req->rw,
|
|
req->bytes);
|
|
|
|
ocf_req_forward_core_init(req, callback);
|
|
|
|
ocf_req_forward_core_io(req, req->rw, req->addr,
|
|
req->bytes, req->offset);
|
|
}
|
|
|
|
void ocf_engine_forward_core_flush_req(struct ocf_request *req,
|
|
ocf_req_end_t callback)
|
|
{
|
|
ocf_core_stats_core_block_update(req->core, req->part_id, req->rw,
|
|
req->bytes);
|
|
|
|
ocf_req_forward_core_init(req, callback);
|
|
|
|
ocf_req_forward_core_flush(req);
|
|
}
|
|
|
|
void ocf_engine_forward_core_discard_req(struct ocf_request *req,
|
|
ocf_req_end_t callback)
|
|
{
|
|
ocf_core_stats_core_block_update(req->core, req->part_id, req->rw,
|
|
req->bytes);
|
|
|
|
ocf_req_forward_core_init(req, callback);
|
|
|
|
ocf_req_forward_core_discard(req, req->addr, req->bytes);
|
|
}
|