Merge pull request #873 from mmichal10/fix-detach-cmpl

Fix detach cmpl
This commit is contained in:
Robert Baldyga 2025-03-27 08:59:32 +01:00 committed by GitHub
commit c7e47e226a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 239 additions and 10 deletions

View File

@ -1,6 +1,6 @@
/*
* Copyright(c) 2012-2022 Intel Corporation
* Copyright(c) 2024 Huawei Technologies
* Copyright(c) 2024-2025 Huawei Technologies
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ocf/ocf.h"
@ -33,7 +33,10 @@ int ocf_d2c_io_fast(struct ocf_request *req)
{
OCF_DEBUG_TRACE(req->cache);
/* Get OCF request - increase reference counter */
/* Increase reference counter - once for submission and second time to
* avoid freeing the request before updating stats
*/
ocf_req_get(req);
ocf_req_get(req);
ocf_engine_forward_core_io_req(req, _ocf_d2c_completion);
@ -46,6 +49,8 @@ int ocf_d2c_io_fast(struct ocf_request *req)
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
req->info.hit_no, req->core_line_count);
ocf_req_put(req);
return 0;
}

View File

@ -3860,14 +3860,14 @@ static void ocf_mngt_cache_detach_finish(ocf_pipeline_t pipeline,
}
_ocf_mngt_cache_set_detached(cache);
ocf_pipeline_destroy(cache->stop_pipeline);
cache->stop_pipeline = NULL;
} else {
ocf_cache_log(cache, log_err,
"Detaching device failed\n");
}
ocf_pipeline_destroy(cache->stop_pipeline);
cache->stop_pipeline = NULL;
context->cmpl(cache, context->priv,
error ?: context->cache_write_error);

View File

@ -170,11 +170,14 @@ static inline struct ocf_request *ocf_req_new_d2c(ocf_queue_t queue,
{
ocf_cache_t cache = ocf_core_get_cache(core);
struct ocf_request *req;
uint32_t request_size = 1;
req = env_mpool_new(cache->owner->resources.req, 1);
req = env_mpool_new(cache->owner->resources.req, request_size);
if (unlikely(!req))
return NULL;
req->alloc_core_line_count = request_size;
ocf_req_init(req, cache, queue, core, addr, bytes, rw);
req->d2c = true;

View File

@ -1,6 +1,6 @@
#
# Copyright(c) 2019-2022 Intel Corporation
# Copyright(c) 2024 Huawei Technologies
# Copyright(c) 2024-2025 Huawei Technologies
# SPDX-License-Identifier: BSD-3-Clause
#
@ -182,6 +182,17 @@ class Core:
if c.results["error"]:
raise OcfError("Couldn't flush cache", c.results["error"])
def detach(self):
self.cache.write_lock()
c = OcfCompletion([("priv", c_void_p), ("error", c_int)])
self.cache.owner.lib.ocf_mngt_cache_detach_core(self.handle, c, None)
c.wait()
self.cache.write_unlock()
if c.results["error"]:
raise OcfError("Couldn't detach core", c.results["error"])
def reset_stats(self):
lib.ocf_core_stats_initialize(self.handle)
@ -207,3 +218,5 @@ lib.ocf_core_stats_initialize.argtypes = [c_void_p]
lib.ocf_core_stats_initialize.restype = c_void_p
lib.ocf_mngt_core_flush.argtypes = [c_void_p, c_void_p, c_void_p]
lib.ocf_mngt_core_flush.restype = c_void_p
lib.ocf_mngt_cache_detach_core.argtypes = [c_void_p, c_void_p, c_void_p]
lib.ocf_mngt_cache_detach_core.restype = c_void_p

View File

@ -1,6 +1,6 @@
#
# Copyright(c) 2019-2022 Intel Corporation
# Copyright(c) 2024 Huawei Technologies
# Copyright(c) 2024-2025 Huawei Technologies
# SPDX-License-Identifier: BSD-3-Clause
#
@ -8,7 +8,7 @@ import pytest
from ctypes import c_int
from random import randint
from pyocf.types.cache import Cache, CacheMode
from pyocf.types.cache import Cache, CacheMode, CleaningPolicy, PromotionPolicy
from pyocf.types.core import Core
from pyocf.types.volume import RamVolume, Volume
from pyocf.types.volume_core import CoreVolume
@ -16,7 +16,7 @@ from pyocf.types.data import Data
from pyocf.types.io import IoDir, Sync
from pyocf.types.queue import Queue
from pyocf.utils import Size as S
from pyocf.types.shared import OcfError, OcfCompletion, CacheLineSize
from pyocf.types.shared import OcfError, OcfErrorCode, OcfCompletion, CacheLineSize
@pytest.mark.parametrize("cache_mode", CacheMode)
@ -89,6 +89,190 @@ def test_remove_dirty_no_flush(pyocf_ctx, cache_mode, cls):
cache.remove_core(core)
@pytest.mark.parametrize("cleaning_policy", CleaningPolicy)
@pytest.mark.parametrize("promotion_policy", PromotionPolicy)
def test_detach_core_detach_cache_cleaning(pyocf_ctx, cleaning_policy, promotion_policy):
cache_device = RamVolume(S.from_MiB(100))
core_device_1 = RamVolume(S.from_MiB(10))
core_device_2 = RamVolume(S.from_MiB(10))
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
core_1 = Core.using_device(core_device_1, name="core_1")
core_2 = Core.using_device(core_device_2, name="core_2")
cache.add_core(core_1)
cache.add_core(core_2)
cache.set_cleaning_policy(cleaning_policy)
cache.set_promotion_policy(promotion_policy)
core_1.detach()
with pytest.raises(OcfError, match="OCF_ERR_CACHE_IN_INCOMPLETE_STATE"):
cache.detach_device()
@pytest.mark.parametrize("cleaning_policy", CleaningPolicy)
@pytest.mark.parametrize("promotion_policy", PromotionPolicy)
def test_detach_core_stop_cache_cleaning(pyocf_ctx, cleaning_policy, promotion_policy):
cache_device = RamVolume(S.from_MiB(100))
core_device_1 = RamVolume(S.from_MiB(10))
core_device_2 = RamVolume(S.from_MiB(10))
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
core_1 = Core.using_device(core_device_1, name="core_1")
core_2 = Core.using_device(core_device_2, name="core_2")
cache.add_core(core_1)
cache.add_core(core_2)
cache.set_cleaning_policy(cleaning_policy)
cache.set_promotion_policy(promotion_policy)
core_1.detach()
cache.stop()
@pytest.mark.parametrize("cleaning_policy", CleaningPolicy)
@pytest.mark.parametrize("promotion_policy", PromotionPolicy)
def test_detach_cache_detach_core_cleaning(pyocf_ctx, cleaning_policy, promotion_policy):
cache_device = RamVolume(S.from_MiB(100))
core_device_1 = RamVolume(S.from_MiB(10))
core_device_2 = RamVolume(S.from_MiB(10))
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
core_1 = Core.using_device(core_device_1, name="core_1")
core_2 = Core.using_device(core_device_2, name="core_2")
cache.add_core(core_1)
cache.add_core(core_2)
cache.set_cleaning_policy(cleaning_policy)
cache.set_promotion_policy(promotion_policy)
for core in [core_1, core_2]:
vol = CoreVolume(core)
queue = core.cache.get_default_queue()
core_size = core.get_stats()["size"]
data = Data(core_size.B)
_io_to_core(vol, queue, data)
core_1.detach()
cache.stop()
@pytest.mark.parametrize("cleaning_policy", CleaningPolicy)
@pytest.mark.parametrize("promotion_policy", PromotionPolicy)
def test_detach_cache_retach_core_cleaning(pyocf_ctx, cleaning_policy, promotion_policy):
cache_device = RamVolume(S.from_MiB(100))
core_device_1 = RamVolume(S.from_MiB(10))
core_device_2 = RamVolume(S.from_MiB(10))
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
core_1 = Core.using_device(core_device_1, name="core_1")
core_2 = Core.using_device(core_device_2, name="core_2")
def _write_cores(cores_list):
for core in cores_list:
vol = CoreVolume(core)
queue = core.cache.get_default_queue()
core_size = core.get_stats()["size"]
data = Data(core_size.B)
_io_to_core(vol, queue, data)
cache.add_core(core_1)
cache.add_core(core_2)
cache.set_cleaning_policy(cleaning_policy)
cache.set_promotion_policy(promotion_policy)
cache.detach_device()
core_1.detach()
_write_cores([core_2])
cache.attach_device(cache_device)
_write_cores([core_2])
cache.add_core(core_1, try_add=True)
_write_cores([core_1, core_2])
cache.stop()
@pytest.mark.parametrize("cleaning_policy", CleaningPolicy)
@pytest.mark.parametrize("promotion_policy", PromotionPolicy)
def test_reattach_cache_reattach_core_cleaning(pyocf_ctx, cleaning_policy, promotion_policy):
cache_device = RamVolume(S.from_MiB(100))
core_device_1 = RamVolume(S.from_MiB(10))
core_device_2 = RamVolume(S.from_MiB(10))
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
core_1 = Core.using_device(core_device_1, name="core_1")
core_2 = Core.using_device(core_device_2, name="core_2")
def _write_cores(cores_list):
for core in cores_list:
vol = CoreVolume(core)
queue = core.cache.get_default_queue()
core_size = core.get_stats()["size"]
data = Data(core_size.B)
_io_to_core(vol, queue, data)
cache.add_core(core_1)
cache.add_core(core_2)
cache.set_cleaning_policy(cleaning_policy)
cache.set_promotion_policy(promotion_policy)
cache.detach_device()
core_1.detach()
cache.add_core(core_1, try_add=True)
cache.attach_device(cache_device)
_write_cores([core_1, core_2])
cache.stop()
@pytest.mark.parametrize("cleaning_policy", CleaningPolicy)
@pytest.mark.parametrize("promotion_policy", PromotionPolicy)
def test_detach_cache_detach_core_load_cleaning(pyocf_ctx, cleaning_policy, promotion_policy):
cache_device = RamVolume(S.from_MiB(100))
core_device_1 = RamVolume(S.from_MiB(10))
core_device_2 = RamVolume(S.from_MiB(10))
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
core_1 = Core.using_device(core_device_1, name="core_1")
core_2 = Core.using_device(core_device_2, name="core_2")
cache.add_core(core_1)
cache.add_core(core_2)
cache.set_cleaning_policy(cleaning_policy)
cache.set_promotion_policy(promotion_policy)
core_1.detach()
cache.stop()
cache = Cache.load_from_device(cache_device)
def test_30add_remove(pyocf_ctx):
# Start cache device
cache_device = RamVolume(S.from_MiB(50))

View File

@ -85,6 +85,30 @@ def test_detach_cache_with_cleaning(pyocf_ctx, cleaning_policy):
cache.stop()
def test_d2c_io(pyocf_ctx):
cache_device = RamVolume(Size.from_MiB(100))
core_device_1 = RamVolume(Size.from_MiB(10))
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
core_1 = Core.using_device(core_device_1, name="core_1")
cache.add_core(core_1)
cache.detach_device()
vol = CoreVolume(core_1)
queue = core_1.cache.get_default_queue()
data = Data(4096)
vol.open()
io = vol.new_io(queue, 0, data.size, IoDir.WRITE, 0, 0)
io.set_data(data)
completion = Sync(io).submit()
vol.close()
assert completion.results["err"] == 0
def test_detach_cache_zero_superblock(pyocf_ctx):
"""Check if superblock is zeroed after detach and the cache device can be reattached without
--force option.