diff --git a/utils/casctl b/utils/casctl index 9c74bd2df..e308ba726 100755 --- a/utils/casctl +++ b/utils/casctl @@ -64,6 +64,12 @@ def add_core_recursive(core, config): eprint('Unable to add core {0} to cache {1}. Reason:\n{2}' .format(core.device, core.cache_id, e.result.stderr)) with_error = True + try: + opencas.configure_core(core) + except opencas.casadm.CasadmError as e: + eprint('Unable to configure core {0} ({1}). Reason:\n{2}' + .format(core.device, core.cache_id, e.result.stderr)) + with_error = True return with_error def init(force): diff --git a/utils/opencas.conf.5 b/utils/opencas.conf.5 index c70091ede..66b251ec9 100644 --- a/utils/opencas.conf.5 +++ b/utils/opencas.conf.5 @@ -24,7 +24,7 @@ Cache device .br Cache mode {wt|wb|wa|pt|wo} .br -Extra fields (optional) ioclass_file=,cleaning_policy=,promotion_policy= +Extra fields (optional) ioclass_file=,cleaning_policy=,cleaning_acp_wake_up=<0-10000>,cleaning_acp_flush_max_buffers=<1-10000>,cleaning_alru_wake_up=<0-3600>,cleaning_alru_flush_max_buffers=<1-10000>,cleaning_alru_staleness_time=<1-3600>,cleaning_alru_activity_threshold=<0-1000000>,promotion_policy=,promotion_nhit_threshold=<2-1000>,promotion_trigger=<0-100> .RE .TP \fB[cores]\fR Cores configuration. Following columns are required: @@ -36,7 +36,7 @@ Core ID <0-4095> .br Core device .br -Extra fields (optional) lazy_startup= +Extra fields (optional) lazy_startup=,seq_cutoff_policy=,seq_cutoff_threshold=<1-4194181> .RE .TP \fBNOTES\fR diff --git a/utils/opencas.py b/utils/opencas.py index a2c6f555a..d30497a6e 100644 --- a/utils/opencas.py +++ b/utils/opencas.py @@ -123,6 +123,18 @@ def set_param(cls, namespace, cache_id, **kwargs): return cls.run_cmd(cmd) + @classmethod + def set_core_param(cls, namespace, cache_id, core_id, **kwargs): + cmd = [cls.casadm_path, + '--set-param', '--name', namespace, + '--cache-id', str(cache_id), + '--core-id', str(core_id)] + + for param, value in kwargs.items(): + cmd += ['--' + param.replace('_', '-'), str(value)] + + return cls.run_cmd(cmd) + @classmethod def get_params(cls, namespace, cache_id, **kwargs): cmd = [cls.casadm_path, @@ -244,8 +256,24 @@ def validate_parameter(self, param_name, param_value): raise ValueError('Invalid path to io_class file') elif param_name == 'cleaning_policy': self.check_cleaning_policy_valid(param_value) + elif param_name == 'cleaning_acp_wake_up': + self.check_cleaning_acp_wake_up_valid(int(param_value)) + elif param_name == 'cleaning_acp_flush_max_buffers': + self.check_cleaning_acp_flush_max_buffers_valid(int(param_value)) + elif param_name == 'cleaning_alru_wake_up': + self.check_cleaning_alru_wake_up_valid(int(param_value)) + elif param_name == 'cleaning_alru_flush_max_buffers': + self.check_cleaning_alru_flush_max_buffers_valid(int(param_value)) + elif param_name == 'cleaning_alru_staleness_time': + self.check_cleaning_alru_staleness_time_valid(int(param_value)) + elif param_name == 'cleaning_alru_activity_threshold': + self.check_cleaning_alru_activity_threshold_valid(int(param_value)) elif param_name == 'promotion_policy': self.check_promotion_policy_valid(param_value) + elif param_name == 'promotion_nhit_threshold': + self.check_promotion_nhit_threshold_valid(int(param_value)) + elif param_name == 'promotion_nhit_trigger': + self.check_promotion_nhit_trigger_valid(int(param_value)) elif param_name == 'cache_line_size': self.check_cache_line_size_valid(param_value) elif param_name == "lazy_startup": @@ -280,6 +308,82 @@ def check_cleaning_policy_valid(self, cleaning_policy): if cleaning_policy.lower() not in ['acp', 'alru', 'nop']: raise ValueError(f'{cleaning_policy} is invalid cleaning policy name') + def check_cleaning_acp_wake_up_valid(self, number): + cleaning_policy = self.params.get('cleaning_policy') + if cleaning_policy != 'acp': + raise ValueError( + f'cleaning_acp_wake_up is invalid param for cleaning_policy {cleaning_policy}' + ) + + if not 0 <= number <= 10000: + raise ValueError( + f'{number} is invalid wake-up number for cleaning-acp' + ) + + def check_cleaning_acp_flush_max_buffers_valid(self, number): + cleaning_policy = self.params.get('cleaning_policy') + if cleaning_policy != 'acp': + raise ValueError( + f'cleaning_acp_flush_max_buffers is invalid param for' + ' cleaning_policy {cleaning_policy}' + ) + + if not 1 <= number <= 10000: + raise ValueError( + f'{number} is invalid flush-max-buffers number for cleaning-acp' + ) + + def check_cleaning_alru_wake_up_valid(self, number): + cleaning_policy = self.params.get('cleaning_policy') + if cleaning_policy != 'alru': + raise ValueError( + f'cleaning_alru_wake_up is invalid param for cleaning_policy {cleaning_policy}' + ) + + if not 0 <= number <= 3600: + raise ValueError( + f'{number} is invalid wake-up number for cleaning-alru' + ) + + def check_cleaning_alru_flush_max_buffers_valid(self, number): + cleaning_policy = self.params.get('cleaning_policy') + if cleaning_policy != 'alru': + raise ValueError( + f'cleaning_alru_flush_max_buffers is invalid param for' + ' cleaning_policy {cleaning_policy}' + ) + + if not 1 <= number <= 10000: + raise ValueError( + f'{number} is invalid flush-max-buffers number for cleaning-alru' + ) + + def check_cleaning_alru_staleness_time_valid(self, number): + cleaning_policy = self.params.get('cleaning_policy') + if cleaning_policy != 'alru': + raise ValueError( + f'cleaning_alru_staleness_time is invalid param for' + ' cleaning_policy {cleaning_policy}' + ) + + if not 1 <= number <= 3600: + raise ValueError( + f'{number} is invalid staleness-time number for cleaning-alru' + ) + + def check_cleaning_alru_activity_threshold_valid(self, number): + cleaning_policy = self.params.get('cleaning_policy') + if cleaning_policy != 'alru': + raise ValueError( + f'cleaning_alru_activity_threshold is invalid param for' + ' cleaning_policy {cleaning_policy}' + ) + + if not 0 <= number <= 1000000: + raise ValueError( + f'{number} is invalid activity-threshold number for cleaning-alru' + ) + def check_lazy_startup_valid(self, lazy_startup): if lazy_startup.lower() not in ["true", "false"]: raise ValueError('{0} is invalid lazy_startup value'.format(lazy_startup)) @@ -288,6 +392,32 @@ def check_promotion_policy_valid(self, promotion_policy): if promotion_policy.lower() not in ['always', 'nhit']: raise ValueError(f'{promotion_policy} is invalid promotion policy name') + def check_promotion_nhit_threshold_valid(self, number): + promotion_policy = self.params.get('promotion_policy') + if promotion_policy != 'nhit': + raise ValueError( + f'promotion_nhit_threshold is invalid param for' + ' promotion_policy {promotion_policy}' + ) + + if not 2 <= number <= 1000: + raise ValueError( + f'{number} is invalid threshold number for promotion-nhit' + ) + + def check_promotion_nhit_trigger_valid(self, number): + promotion_policy = self.params.get('promotion_policy') + if promotion_policy != 'nhit': + raise ValueError( + f'promotion_nhit_trigger is invalid param for' + ' promotion_policy {promotion_policy}' + ) + + if not 0 <= number <= 100: + raise ValueError( + f'{number} is invalid trigger number for promotion-nhit' + ) + def check_cache_line_size_valid(self, cache_line_size): if cache_line_size not in ['4', '8', '16', '32', '64']: raise ValueError(f'{cache_line_size} is invalid cache line size') @@ -373,6 +503,10 @@ def validate_parameter(self, param_name, param_value): raise ValueError( f"{param_value} is invalid value for '{param_name}' core param" ) + elif param_name == "seq_cutoff_policy": + self.check_seq_cutoff_policy_valid(param_value) + elif param_name == "seq_cutoff_threshold": + self.check_seq_cutoff_threshold_valid(int(param_value)) else: raise ValueError(f"'{param_name}' is invalid core param name") @@ -390,6 +524,18 @@ def check_recursive(self): if int(device_cache_id) == self.cache_id: raise ValueError('Recursive configuration detected') + def check_seq_cutoff_policy_valid(self, seq_cutoff_policy): + if seq_cutoff_policy not in ['always', 'full', 'never']: + raise ValueError( + f'{seq_cutoff_policy} is invalid seq-cutoff policy name' + ) + + def check_seq_cutoff_threshold_valid(self, number): + if not 1 <= number <= 4194181: + raise ValueError( + f'{number} is invalid threshold number for seq-cutoff' + ) + def to_line(self): ret = f"{self.cache_id}\t{self.core_id}\t{self.device}" for i, (param, value) in enumerate(self.params.items()): @@ -559,10 +705,60 @@ def configure_cache(cache): casadm.set_param( "cleaning", cache_id=cache.cache_id, policy=cache.params["cleaning_policy"] ) + + if "cleaning_acp_wake_up" in cache.params: + casadm.set_param( + "cleaning-acp", cache_id=cache.cache_id, + wake_up=cache.params["cleaning_acp_wake_up"] + ) + + if "cleaning_acp_flush_max_buffers" in cache.params: + casadm.set_param( + "cleaning-acp", cache_id=cache.cache_id, + flush_max_buffers=cache.params["cleaning_acp_flush_max_buffers"] + ) + + if "cleaning_alru_wake_up" in cache.params: + casadm.set_param( + "cleaning-alru", cache_id=cache.cache_id, + wake_up=cache.params["cleaning_alru_wake_up"] + ) + + if "cleaning_alru_flush_max_buffers" in cache.params: + casadm.set_param( + "cleaning-alru", cache_id=cache.cache_id, + flush_max_buffers=cache.params["cleaning_alru_flush_max_buffers"] + ) + + if "cleaning_alru_staleness_time" in cache.params: + casadm.set_param( + "cleaning-alru", cache_id=cache.cache_id, + staleness_time=cache.params["cleaning_alru_staleness_time"] + ) + + if "cleaning_alru_activity_threshold" in cache.params: + casadm.set_param( + "cleaning-alru", cache_id=cache.cache_id, + activity_threshold=cache.params["cleaning_alru_activity_threshold"] + ) if "promotion_policy" in cache.params: casadm.set_param( "promotion", cache_id=cache.cache_id, policy=cache.params["promotion_policy"] ) + + if "promotion_nhit_threshold" in cache.params: + casadm.set_param( + "promotion-nhit", + cache_id=cache.cache_id, + threshold=cache.params["promotion_nhit_threshold"] + ) + + if "promotion_nhit_trigger" in cache.params: + casadm.set_param( + "promotion-nhit", + cache_id=cache.cache_id, + trigger=cache.params["promotion_nhit_trigger"] + ) if "ioclass_file" in cache.params: casadm.io_class_load_config( cache_id=cache.cache_id, ioclass_file=cache.params["ioclass_file"] @@ -576,6 +772,21 @@ def add_core(core, attach): core_id=core.core_id, try_add=attach) + +def configure_core(core): + params = dict() + if "seq_cutoff_policy" in core.params: + params['policy'] = core.params["seq_cutoff_policy"] + + if "seq_cutoff_threshold" in core.params: + params['threshold'] = core.params["seq_cutoff_threshold"] + + if params: + casadm.set_core_param( + "seq-cutoff", cache_id=core.cache_id, core_id=core.core_id, **params + ) + + # Another helper functions