Merge pull request #461 from mmichal10/evict-pinned
Evict pinned overflown ioclass
This commit is contained in:
commit
91cbeed611
@ -62,7 +62,7 @@ static inline uint32_t ocf_evict_part_do(ocf_cache_t cache,
|
||||
|
||||
static inline uint32_t ocf_evict_partitions(ocf_cache_t cache,
|
||||
ocf_queue_t io_queue, uint32_t evict_cline_no,
|
||||
bool overflown_only, uint32_t max_priority)
|
||||
bool overflown_only, int16_t max_priority)
|
||||
{
|
||||
uint32_t to_evict = 0, evicted = 0;
|
||||
struct ocf_user_part *part;
|
||||
@ -84,8 +84,9 @@ static inline uint32_t ocf_evict_partitions(ocf_cache_t cache,
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if (!part->config->flags.eviction) {
|
||||
/* no more partitions available for viction
|
||||
if (!overflown_only && !part->config->flags.eviction) {
|
||||
/* If partition is overflown it should be evcited
|
||||
* even if its pinned
|
||||
*/
|
||||
break;
|
||||
}
|
||||
@ -132,8 +133,9 @@ static inline uint32_t ocf_evict_do(ocf_cache_t cache,
|
||||
* priority in this case, as overflown partitions should
|
||||
* free its cachelines regardless of destination partition
|
||||
* priority. */
|
||||
|
||||
evicted = ocf_evict_partitions(cache, io_queue, evict_cline_no,
|
||||
true, OCF_IO_CLASS_PRIO_HIGHEST);
|
||||
true, OCF_IO_CLASS_PRIO_PINNED);
|
||||
if (evicted >= evict_cline_no)
|
||||
return evicted;
|
||||
/* Not enough cachelines in overflown partitions. Go through
|
||||
|
@ -4,6 +4,7 @@
|
||||
#
|
||||
|
||||
import logging
|
||||
from math import ceil, isclose
|
||||
from ctypes import c_int
|
||||
|
||||
import pytest
|
||||
@ -12,7 +13,7 @@ from pyocf.types.cache import Cache, CacheMode
|
||||
from pyocf.types.core import Core
|
||||
from pyocf.types.data import Data
|
||||
from pyocf.types.io import IoDir
|
||||
from pyocf.types.shared import OcfCompletion, CacheLineSize, SeqCutOffPolicy
|
||||
from pyocf.types.shared import OcfCompletion, CacheLineSize, SeqCutOffPolicy, CacheLines
|
||||
from pyocf.types.volume import Volume
|
||||
from pyocf.utils import Size
|
||||
|
||||
@ -74,10 +75,89 @@ def test_write_size_greater_than_cache(pyocf_ctx, mode: CacheMode, cls: CacheLin
|
||||
io_size_bigger_than_cache.blocks_4k
|
||||
|
||||
|
||||
def send_io(exported_obj: Core, data: Data, addr: int = 0):
|
||||
@pytest.mark.parametrize("cls", CacheLineSize)
|
||||
def test_evict_overflown_pinned(pyocf_ctx, cls: CacheLineSize):
|
||||
""" Verify if overflown pinned ioclass is evicted """
|
||||
cache_device = Volume(Size.from_MiB(35))
|
||||
core_device = Volume(Size.from_MiB(100))
|
||||
cache = Cache.start_on_device(
|
||||
cache_device, cache_mode=CacheMode.WT, cache_line_size=cls
|
||||
)
|
||||
core = Core.using_device(core_device)
|
||||
cache.add_core(core)
|
||||
|
||||
test_ioclass_id = 1
|
||||
pinned_ioclass_id = 2
|
||||
pinned_ioclass_max_occupancy = 10
|
||||
|
||||
cache.configure_partition(
|
||||
part_id=test_ioclass_id,
|
||||
name="default_ioclass",
|
||||
min_size=0,
|
||||
max_size=100,
|
||||
priority=1,
|
||||
)
|
||||
cache.configure_partition(
|
||||
part_id=pinned_ioclass_id,
|
||||
name="pinned_ioclass",
|
||||
min_size=0,
|
||||
max_size=pinned_ioclass_max_occupancy,
|
||||
priority=-1,
|
||||
)
|
||||
|
||||
cache.set_seq_cut_off_policy(SeqCutOffPolicy.NEVER)
|
||||
|
||||
cache_size = cache.get_stats()["conf"]["size"]
|
||||
|
||||
data = Data(4096)
|
||||
|
||||
# Populate cache with data
|
||||
for i in range(cache_size.blocks_4k):
|
||||
send_io(core, data, i * 4096, test_ioclass_id)
|
||||
|
||||
part_current_size = CacheLines(
|
||||
cache.get_partition_info(part_id=test_ioclass_id)["_curr_size"], cls
|
||||
)
|
||||
assert isclose(
|
||||
part_current_size.blocks_4k, cache_size.blocks_4k, abs_tol=Size(cls).blocks_4k
|
||||
), "Failed to populate the default partition"
|
||||
|
||||
# Repart - force overflow of second partition occupancy limit
|
||||
pinned_double_size = ceil(
|
||||
(cache_size.blocks_4k * pinned_ioclass_max_occupancy * 2) / 100
|
||||
)
|
||||
for i in range(pinned_double_size):
|
||||
send_io(core, data, i * 4096, pinned_ioclass_id)
|
||||
|
||||
part_current_size = CacheLines(
|
||||
cache.get_partition_info(part_id=pinned_ioclass_id)["_curr_size"], cls
|
||||
)
|
||||
assert isclose(
|
||||
part_current_size.blocks_4k, pinned_double_size, abs_tol=Size(cls).blocks_4k
|
||||
), "Occupancy of pinned ioclass doesn't match expected value"
|
||||
|
||||
# Trigger IO to the default ioclass - force eviction from overlown ioclass
|
||||
for i in range(cache_size.blocks_4k):
|
||||
send_io(core, data, (cache_size.blocks_4k + i) * 4096, test_ioclass_id)
|
||||
|
||||
part_current_size = CacheLines(
|
||||
cache.get_partition_info(part_id=pinned_ioclass_id)["_curr_size"], cls
|
||||
)
|
||||
assert isclose(
|
||||
part_current_size.blocks_4k,
|
||||
ceil(cache_size.blocks_4k * 0.1),
|
||||
abs_tol=Size(cls).blocks_4k,
|
||||
), "Overflown part has not been evicted"
|
||||
|
||||
|
||||
def send_io(exported_obj: Core, data: Data, addr: int = 0, target_ioclass: int = 0):
|
||||
io = exported_obj.new_io(
|
||||
exported_obj.cache.get_default_queue(),
|
||||
addr, data.size, IoDir.WRITE, 0, 0
|
||||
addr,
|
||||
data.size,
|
||||
IoDir.WRITE,
|
||||
target_ioclass,
|
||||
0,
|
||||
)
|
||||
|
||||
io.set_data(data)
|
||||
|
Loading…
Reference in New Issue
Block a user