From df7ed6920cc73ed00ec27f265563154354e51dcf Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Mon, 16 May 2022 14:16:36 +0200 Subject: [PATCH] Fix ops(flush) engine Flush I/O should be forwarded to core and cache device. In case of core this is simple - just mirror the I/O from the top volume. Since cache data is owned by OCF it makes sense to send a simple flush I/O with 0 address and size. Current implementation attempts to use cache data I/O interface (ocf_submit_cache_reqs function) instead of submitting empty flush to the underlying cache device. This function is designed to read/write from mapped cachelines while there is no traversation/mapping performed on flush I/O. If request map allocation succeeds, this results in sending I/O to addres 0 with size and flags inherited from the top adapter I/O. This doesn't make any sense, and can even result in invalid I/O if the size is greater than cache device size. Even worse, if flush request map allocation fails (which happens always in case of large flush requests) then the erroneous call to ocf_submit_cache_reqs results in NULL pointer dereference. Signed-off-by: Adam Rutkowski --- src/engine/engine_ops.c | 11 ++++------- src/utils/utils_io.c | 17 +++++++++++++++++ src/utils/utils_io.h | 4 +++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/engine/engine_ops.c b/src/engine/engine_ops.c index a0b9beb..c65fc0b 100644 --- a/src/engine/engine_ops.c +++ b/src/engine/engine_ops.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2012-2021 Intel Corporation + * Copyright(c) 2012-2022 Intel Corporation * SPDX-License-Identifier: BSD-3-Clause */ #include "ocf/ocf.h" @@ -37,10 +37,6 @@ static void _ocf_engine_ops_complete(struct ocf_request *req, int error) int ocf_engine_ops(struct ocf_request *req) { - struct ocf_cache *cache = req->cache; - - OCF_DEBUG_TRACE(req->cache); - /* Get OCF request - increase reference counter */ ocf_req_get(req); @@ -51,8 +47,9 @@ int ocf_engine_ops(struct ocf_request *req) ocf_submit_volume_req(&req->core->volume, req, _ocf_engine_ops_complete); - ocf_submit_cache_reqs(cache, req, req->rw, 0, req->byte_length, - 1, _ocf_engine_ops_complete); + + /* submit flush to cache device */ + ocf_submit_cache_flush(req, _ocf_engine_ops_complete); /* Put OCF request - decrease reference counter */ ocf_req_put(req); diff --git a/src/utils/utils_io.c b/src/utils/utils_io.c index f969646..f33ffb8 100644 --- a/src/utils/utils_io.c +++ b/src/utils/utils_io.c @@ -224,6 +224,23 @@ static void ocf_submit_volume_req_cmpl(struct ocf_io *io, int error) ocf_io_put(io); } +void ocf_submit_cache_flush(struct ocf_request *req, ocf_req_end_t callback) +{ + uint64_t flags = req->ioi.io.flags; + struct ocf_io *io; + + io = ocf_new_cache_io(req->cache, req->io_queue, 0, 0, OCF_WRITE, 0, + flags); + if (!io) { + callback(req, -OCF_ERR_NO_MEM); + return; + } + + ocf_io_set_cmpl(io, req, callback, ocf_submit_volume_req_cmpl); + + ocf_volume_submit_flush(io); +} + void ocf_submit_cache_reqs(struct ocf_cache *cache, struct ocf_request *req, int dir, uint64_t offset, uint64_t size, unsigned int reqs, ocf_req_end_t callback) diff --git a/src/utils/utils_io.h b/src/utils/utils_io.h index c24c1d9..4419455 100644 --- a/src/utils/utils_io.h +++ b/src/utils/utils_io.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2012-2021 Intel Corporation + * Copyright(c) 2012-2022 Intel Corporation * SPDX-License-Identifier: BSD-3-Clause */ @@ -64,6 +64,8 @@ void ocf_submit_cache_reqs(struct ocf_cache *cache, struct ocf_request *req, int dir, uint64_t offset, uint64_t size, unsigned int reqs, ocf_req_end_t callback); +void ocf_submit_cache_flush(struct ocf_request *req, ocf_req_end_t callback); + static inline struct ocf_io *ocf_new_cache_io(ocf_cache_t cache, ocf_queue_t queue, uint64_t addr, uint32_t bytes, uint32_t dir, uint32_t io_class, uint64_t flags)