commit
c7e47e226a
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright(c) 2012-2022 Intel Corporation
|
* Copyright(c) 2012-2022 Intel Corporation
|
||||||
* Copyright(c) 2024 Huawei Technologies
|
* Copyright(c) 2024-2025 Huawei Technologies
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
#include "ocf/ocf.h"
|
#include "ocf/ocf.h"
|
||||||
@ -33,7 +33,10 @@ int ocf_d2c_io_fast(struct ocf_request *req)
|
|||||||
{
|
{
|
||||||
OCF_DEBUG_TRACE(req->cache);
|
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_req_get(req);
|
||||||
|
|
||||||
ocf_engine_forward_core_io_req(req, _ocf_d2c_completion);
|
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,
|
ocf_core_stats_request_pt_update(req->core, req->part_id, req->rw,
|
||||||
req->info.hit_no, req->core_line_count);
|
req->info.hit_no, req->core_line_count);
|
||||||
|
|
||||||
|
ocf_req_put(req);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3860,14 +3860,14 @@ static void ocf_mngt_cache_detach_finish(ocf_pipeline_t pipeline,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ocf_mngt_cache_set_detached(cache);
|
_ocf_mngt_cache_set_detached(cache);
|
||||||
|
|
||||||
|
ocf_pipeline_destroy(cache->stop_pipeline);
|
||||||
|
cache->stop_pipeline = NULL;
|
||||||
} else {
|
} else {
|
||||||
ocf_cache_log(cache, log_err,
|
ocf_cache_log(cache, log_err,
|
||||||
"Detaching device failed\n");
|
"Detaching device failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ocf_pipeline_destroy(cache->stop_pipeline);
|
|
||||||
cache->stop_pipeline = NULL;
|
|
||||||
|
|
||||||
context->cmpl(cache, context->priv,
|
context->cmpl(cache, context->priv,
|
||||||
error ?: context->cache_write_error);
|
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);
|
ocf_cache_t cache = ocf_core_get_cache(core);
|
||||||
struct ocf_request *req;
|
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))
|
if (unlikely(!req))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
req->alloc_core_line_count = request_size;
|
||||||
|
|
||||||
ocf_req_init(req, cache, queue, core, addr, bytes, rw);
|
ocf_req_init(req, cache, queue, core, addr, bytes, rw);
|
||||||
|
|
||||||
req->d2c = true;
|
req->d2c = true;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Copyright(c) 2019-2022 Intel Corporation
|
# Copyright(c) 2019-2022 Intel Corporation
|
||||||
# Copyright(c) 2024 Huawei Technologies
|
# Copyright(c) 2024-2025 Huawei Technologies
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -182,6 +182,17 @@ class Core:
|
|||||||
if c.results["error"]:
|
if c.results["error"]:
|
||||||
raise OcfError("Couldn't flush cache", 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):
|
def reset_stats(self):
|
||||||
lib.ocf_core_stats_initialize(self.handle)
|
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_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.argtypes = [c_void_p, c_void_p, c_void_p]
|
||||||
lib.ocf_mngt_core_flush.restype = 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) 2019-2022 Intel Corporation
|
||||||
# Copyright(c) 2024 Huawei Technologies
|
# Copyright(c) 2024-2025 Huawei Technologies
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ import pytest
|
|||||||
from ctypes import c_int
|
from ctypes import c_int
|
||||||
|
|
||||||
from random import randint
|
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.core import Core
|
||||||
from pyocf.types.volume import RamVolume, Volume
|
from pyocf.types.volume import RamVolume, Volume
|
||||||
from pyocf.types.volume_core import CoreVolume
|
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.io import IoDir, Sync
|
||||||
from pyocf.types.queue import Queue
|
from pyocf.types.queue import Queue
|
||||||
from pyocf.utils import Size as S
|
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)
|
@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)
|
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):
|
def test_30add_remove(pyocf_ctx):
|
||||||
# Start cache device
|
# Start cache device
|
||||||
cache_device = RamVolume(S.from_MiB(50))
|
cache_device = RamVolume(S.from_MiB(50))
|
||||||
|
@ -85,6 +85,30 @@ def test_detach_cache_with_cleaning(pyocf_ctx, cleaning_policy):
|
|||||||
cache.stop()
|
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):
|
def test_detach_cache_zero_superblock(pyocf_ctx):
|
||||||
"""Check if superblock is zeroed after detach and the cache device can be reattached without
|
"""Check if superblock is zeroed after detach and the cache device can be reattached without
|
||||||
--force option.
|
--force option.
|
||||||
|
Loading…
Reference in New Issue
Block a user