Merge pull request #461 from mmichal10/evict-pinned

Evict pinned overflown ioclass
This commit is contained in:
Robert Baldyga 2021-02-16 13:55:52 +01:00 committed by GitHub
commit 91cbeed611
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 7 deletions

View File

@ -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, static inline uint32_t ocf_evict_partitions(ocf_cache_t cache,
ocf_queue_t io_queue, uint32_t evict_cline_no, 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; uint32_t to_evict = 0, evicted = 0;
struct ocf_user_part *part; struct ocf_user_part *part;
@ -84,8 +84,9 @@ static inline uint32_t ocf_evict_partitions(ocf_cache_t cache,
*/ */
break; break;
} }
if (!part->config->flags.eviction) { if (!overflown_only && !part->config->flags.eviction) {
/* no more partitions available for viction /* If partition is overflown it should be evcited
* even if its pinned
*/ */
break; break;
} }
@ -132,8 +133,9 @@ static inline uint32_t ocf_evict_do(ocf_cache_t cache,
* priority in this case, as overflown partitions should * priority in this case, as overflown partitions should
* free its cachelines regardless of destination partition * free its cachelines regardless of destination partition
* priority. */ * priority. */
evicted = ocf_evict_partitions(cache, io_queue, evict_cline_no, 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) if (evicted >= evict_cline_no)
return evicted; return evicted;
/* Not enough cachelines in overflown partitions. Go through /* Not enough cachelines in overflown partitions. Go through

View File

@ -4,6 +4,7 @@
# #
import logging import logging
from math import ceil, isclose
from ctypes import c_int from ctypes import c_int
import pytest import pytest
@ -12,7 +13,7 @@ from pyocf.types.cache import Cache, CacheMode
from pyocf.types.core import Core from pyocf.types.core import Core
from pyocf.types.data import Data from pyocf.types.data import Data
from pyocf.types.io import IoDir 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.types.volume import Volume
from pyocf.utils import Size 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 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( io = exported_obj.new_io(
exported_obj.cache.get_default_queue(), 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) io.set_data(data)