From 2719804d384bf769eba96908333af544c26f1253 Mon Sep 17 00:00:00 2001 From: Daniel Madej Date: Fri, 9 Oct 2020 12:15:42 +0200 Subject: [PATCH 1/2] Add class for cas_cache parameters configuration Update test_framework Signed-off-by: Daniel Madej --- test/functional/api/cas/cache_config.py | 118 ++++++++++++++++++++++++ test/functional/test-framework | 2 +- 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/test/functional/api/cas/cache_config.py b/test/functional/api/cas/cache_config.py index 6eba5c8..de97969 100644 --- a/test/functional/api/cas/cache_config.py +++ b/test/functional/api/cas/cache_config.py @@ -6,6 +6,7 @@ from aenum import Enum, IntFlag from attotime import attotimedelta +from test_utils.os_utils import get_kernel_module_parameter from test_utils.size import Size, Unit @@ -263,6 +264,114 @@ class PromotionParametersNhit: return nhit_params +# Specify layout of metadata on SSD +class MetadataLayout(Enum): + striping = 0 + sequential = 1 + DEFAULT = striping + + +# Specify how IO requests unaligned to 4KiB should be handled +class UnalignedIo(Enum): + PT = 0 # use PT mode + cache = 1 # use current cache mode + DEFAULT = cache + + +# Specify if IO scheduler will be used when handling IO requests +class UseIoScheduler(Enum): + off = 0 + on = 1 + DEFAULT = on + + +class KernelParameters: + seq_cut_off_mb_DEFAULT = 1 + max_writeback_queue_size_DEFAULT = 65536 + writeback_queue_unblock_size_DEFAULT = 60000 + + def __init__( + self, + metadata_layout: MetadataLayout = None, + unaligned_io: UnalignedIo = None, + use_io_scheduler: UseIoScheduler = None, + seq_cut_off_mb: int = None, + max_writeback_queue_size: int = None, + writeback_queue_unblock_size: int = None + ): + self.metadata_layout = metadata_layout + self.unaligned_io = unaligned_io + self.use_io_scheduler = use_io_scheduler + # Specify default sequential cut off threshold value in MiB + # 0 - sequential cut off disabled, 1 or larger = sequential cut off threshold (default is 1) + self.seq_cut_off_mb = seq_cut_off_mb + # Specify optimal write queue size, default - 65536 + self.max_writeback_queue_size = max_writeback_queue_size + # Specify unblock threshold for write queue, default - 60000 + self.writeback_queue_unblock_size = writeback_queue_unblock_size + + def __eq__(self, other): + return ( + equal_or_default(self.metadata_layout, other.metadata_layout, MetadataLayout.DEFAULT) + and equal_or_default(self.unaligned_io, other.unaligned_io, UnalignedIo.DEFAULT) + and equal_or_default( + self.use_io_scheduler, other.use_io_scheduler, UseIoScheduler.DEFAULT + ) + and equal_or_default( + self.seq_cut_off_mb, other.seq_cut_off_mb, + self.seq_cut_off_mb_DEFAULT + ) + and equal_or_default( + self.max_writeback_queue_size, other.max_writeback_queue_size, + self.max_writeback_queue_size_DEFAULT + ) + and equal_or_default( + self.writeback_queue_unblock_size, other.writeback_queue_unblock_size, + self.writeback_queue_unblock_size_DEFAULT + ) + ) + + @classmethod + def DEFAULT(cls): + return KernelParameters( + MetadataLayout.DEFAULT, + UnalignedIo.DEFAULT, + UseIoScheduler.DEFAULT, + cls.seq_cut_off_mb_DEFAULT, + cls.max_writeback_queue_size_DEFAULT, + cls.writeback_queue_unblock_size_DEFAULT + ) + + @staticmethod + def read_current_settings(): + module = "cas_cache" + return KernelParameters( + MetadataLayout(int(get_kernel_module_parameter(module, "metadata_layout"))), + UnalignedIo(int(get_kernel_module_parameter(module, "unaligned_io"))), + UseIoScheduler(int(get_kernel_module_parameter(module, "use_io_scheduler"))), + int(get_kernel_module_parameter(module, "seq_cut_off_mb")), + int(get_kernel_module_parameter(module, "max_writeback_queue_size")), + int(get_kernel_module_parameter(module, "writeback_queue_unblock_size")) + ) + + def get_parameter_dictionary(self): + params = {} + if self.metadata_layout not in [None, MetadataLayout.DEFAULT]: + params["metadata_layout"] = str(self.metadata_layout.value) + if self.unaligned_io not in [None, UnalignedIo.DEFAULT]: + params["unaligned_io"] = str(self.unaligned_io.value) + if self.use_io_scheduler not in [None, UseIoScheduler.DEFAULT]: + params["use_io_scheduler"] = str(self.use_io_scheduler.value) + if self.seq_cut_off_mb not in [None, self.seq_cut_off_mb_DEFAULT]: + params["seq_cut_off_mb"] = str(self.seq_cut_off_mb) + if self.max_writeback_queue_size not in [None, self.max_writeback_queue_size_DEFAULT]: + params["max_writeback_queue_size"] = str(self.max_writeback_queue_size) + if (self.writeback_queue_unblock_size not in + [None, self.writeback_queue_unblock_size_DEFAULT]): + params["writeback_queue_unblock_size"] = str(self.writeback_queue_unblock_size) + return params + + # TODO: Use case for this will be to iterate over configurations (kernel params such as # TODO: io scheduler, metadata layout) and prepare env before starting cache class CacheConfig: @@ -273,12 +382,14 @@ class CacheConfig: cleaning_policy=CleaningPolicy.DEFAULT, eviction_policy=EvictionPolicy.DEFAULT, metadata_mode=MetadataMode.normal, + kernel_parameters=None ): self.cache_line_size = cache_line_size self.cache_mode = cache_mode self.cleaning_policy = cleaning_policy self.eviction_policy = eviction_policy self.metadata_mode = metadata_mode + self.kernel_parameters = kernel_parameters def __eq__(self, other): return ( @@ -287,4 +398,11 @@ class CacheConfig: and self.cleaning_policy == other.cleaning_policy and self.eviction_policy == other.eviction_policy and self.metadata_mode == other.metadata_mode + and equal_or_default( + self.kernel_parameters, other.kernel_parameters, KernelParameters.DEFAULT + ) ) + + +def equal_or_default(item1, item2, default): + return (item1 if item1 is not None else default) == (item2 if item2 is not None else default) diff --git a/test/functional/test-framework b/test/functional/test-framework index 6f60cfc..994f2d6 160000 --- a/test/functional/test-framework +++ b/test/functional/test-framework @@ -1 +1 @@ -Subproject commit 6f60cfc05187d8cde5e3b3e613b13dfc2b0b3b77 +Subproject commit 994f2d6fdeab9cee33f517276718708f27003d5d From f3dd0479172ef893cb431744754cf902d8b61d91 Mon Sep 17 00:00:00 2001 From: Daniel Madej Date: Fri, 9 Oct 2020 12:20:10 +0200 Subject: [PATCH 2/2] Reload cas_cache if its params need to be changed Before starting cache, the method checks if current kernel module params are equal to configured (or default if configuration is default). If not then kernel module is reloaded with proper parameters. Signed-off-by: Daniel Madej --- test/functional/api/cas/casadm.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/functional/api/cas/casadm.py b/test/functional/api/cas/casadm.py index 15e8752..f148c85 100644 --- a/test/functional/api/cas/casadm.py +++ b/test/functional/api/cas/casadm.py @@ -6,10 +6,12 @@ from typing import List from api.cas.cache import Cache -from api.cas.cache_config import CacheLineSize, CacheMode, SeqCutOffPolicy, CleaningPolicy +from api.cas.cache_config import CacheLineSize, CacheMode, SeqCutOffPolicy, CleaningPolicy, \ + KernelParameters from api.cas.core import Core from core.test_run import TestRun from storage_devices.device import Device +from test_utils.os_utils import reload_kernel_module from test_utils.output import CmdException from test_utils.size import Size, Unit from .casadm_params import * @@ -23,7 +25,11 @@ def help(shortcut: bool = False): def start_cache(cache_dev: Device, cache_mode: CacheMode = None, cache_line_size: CacheLineSize = None, cache_id: int = None, - force: bool = False, load: bool = False, shortcut: bool = False): + force: bool = False, load: bool = False, shortcut: bool = False, + kernel_params: KernelParameters = KernelParameters()): + if kernel_params != KernelParameters.read_current_settings(): + reload_kernel_module("cas_cache", kernel_params.get_parameter_dictionary()) + _cache_line_size = None if cache_line_size is None else str( int(cache_line_size.value.get_value(Unit.KibiByte))) _cache_id = None if cache_id is None else str(cache_id) @@ -33,7 +39,6 @@ def start_cache(cache_dev: Device, cache_mode: CacheMode = None, cache_id=_cache_id, force=force, load=load, shortcut=shortcut)) if output.exit_code != 0: raise CmdException("Failed to start cache.", output) - return Cache(cache_dev) @@ -126,7 +131,6 @@ def load_cache(device: Device, shortcut: bool = False): load_cmd(cache_dev=device.system_path, shortcut=shortcut)) if output.exit_code != 0: raise CmdException("Failed to load cache.", output) - return Cache(device)