volume: Introduce general IO forward mechanism

Allow the core volume IOs to be forwarded directly to backend volumes to
avoid unnecessary allocations.

Signed-off-by: Robert Baldyga <robert.baldyga@huawei.com>
Signed-off-by: Michal Mielewczyk <michal.mielewczyk@huawei.com>
This commit is contained in:
Robert Baldyga
2023-08-22 21:11:25 +02:00
committed by Michal Mielewczyk
parent edce2c26a5
commit 7e73de0d51
10 changed files with 548 additions and 3 deletions

162
src/engine/engine_io.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* 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->byte_position % ocf_line_size(cache);
uint32_t first_cl = ocf_bytes_2_lines(cache, offset + seek);
uint64_t addr;
req->cache_forward_end = 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->byte_length);
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;
req->cache_forward_end = callback;
if (ocf_engine_is_sequential(req)) {
addr = cache->device->metadata_offset;
addr += req->map[0].coll_idx * ocf_line_size(cache);
addr += req->byte_position % ocf_line_size(cache);
ocf_core_stats_cache_block_update(req->core, req->part_id,
dir, req->byte_length);
ocf_req_forward_cache_io(req, dir, addr, req->byte_length,
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->byte_position) %
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->byte_position + req->byte_length) %
ocf_line_size(cache))) % ocf_line_size(cache);
bytes -= skip;
}
bytes = OCF_MIN(bytes, req->byte_length - 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->byte_length);
ocf_req_forward_cache_put(req);
}
void ocf_engine_forward_cache_flush_req(struct ocf_request *req,
ocf_req_end_t callback)
{
req->cache_forward_end = callback;
ocf_req_forward_cache_flush(req);
}
void ocf_engine_forward_cache_discard_req(struct ocf_request *req,
ocf_req_end_t callback)
{
req->cache_forward_end = callback;
ocf_req_forward_cache_discard(req, req->byte_position,
req->byte_length);
}
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->byte_length);
req->core_forward_end = callback;
ocf_req_forward_core_io(req, req->rw, req->byte_position,
req->byte_length, 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->byte_length);
req->core_forward_end = 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->byte_length);
req->core_forward_end = callback;
ocf_req_forward_core_discard(req, req->byte_position, req->byte_length);
}

32
src/engine/engine_io.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright(c) 2024 Huawei Technologies
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ENGINE_IO_H_
#define ENGINE_IO_H_
#include "../ocf_request.h"
void ocf_engine_forward_cache_io(struct ocf_request *req, int dir,
uint64_t offset, uint64_t size, ocf_req_end_t callback);
void ocf_engine_forward_cache_io_req(struct ocf_request *req, int dir,
ocf_req_end_t callback);
void ocf_engine_forward_cache_flush_req(struct ocf_request *req,
ocf_req_end_t callback);
void ocf_engine_forward_cache_discard_req(struct ocf_request *req,
ocf_req_end_t callback);
void ocf_engine_forward_core_io_req(struct ocf_request *req,
ocf_req_end_t callback);
void ocf_engine_forward_core_flush_req(struct ocf_request *req,
ocf_req_end_t callback);
void ocf_engine_forward_core_discard_req(struct ocf_request *req,
ocf_req_end_t callback);
#endif /* ENGINE_IO_H_ */