commit
c7e47e226a
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user