From 3e171272fffdb2df6c182e1c00ea7c6a9b5ba5e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= Date: Mon, 15 Apr 2024 16:53:23 +0200 Subject: [PATCH] Refactor dynamic tuning functionality - Add a new global option "dynamic_plugins" which can be used to globally enable dynamic tuning only for specific plugins. - Let plugins choose between the default (periodic) dynamic tuning and their own implementation. - Remove the "runtime" option from the scheduler plugin and integrate its functionality into dynamic tuning. Currently, the scheduler plugin is the only dynamic plugin with its own implementation of dynamic tuning (not initiated periodically by the main daemon thread). - Adjust default global configuration so that dynamic tuning is enabled by default, but only for the scheduler plugin. --- profiles/openshift/tuned.conf | 2 +- .../runtest.sh | 2 +- tuned-main.conf | 7 +- tuned/consts.py | 1 + tuned/daemon/application.py | 28 +++++- tuned/daemon/controller.py | 10 +-- tuned/daemon/daemon.py | 15 ++-- tuned/plugins/base.py | 61 ++++++++----- tuned/plugins/hotplug.py | 4 +- tuned/plugins/instance/instance.py | 12 +-- tuned/plugins/plugin_acpi.py | 15 ++-- tuned/plugins/plugin_audio.py | 15 ++-- tuned/plugins/plugin_bootloader.py | 14 +-- tuned/plugins/plugin_cpu.py | 23 +++-- tuned/plugins/plugin_disk.py | 21 +++-- tuned/plugins/plugin_eeepc_she.py | 15 +++- tuned/plugins/plugin_irqbalance.py | 11 +-- tuned/plugins/plugin_modules.py | 14 +-- tuned/plugins/plugin_mounts.py | 15 ++-- tuned/plugins/plugin_net.py | 16 +++- tuned/plugins/plugin_rtentsk.py | 12 ++- tuned/plugins/plugin_scheduler.py | 89 ++++++++++--------- tuned/plugins/plugin_script.py | 14 +-- tuned/plugins/plugin_scsi_host.py | 15 ++-- tuned/plugins/plugin_selinux.py | 15 ++-- tuned/plugins/plugin_service.py | 14 +-- tuned/plugins/plugin_sysctl.py | 12 ++- tuned/plugins/plugin_sysfs.py | 14 +-- tuned/plugins/plugin_systemd.py | 11 +-- tuned/plugins/plugin_uncore.py | 15 ++-- tuned/plugins/plugin_usb.py | 15 ++-- tuned/plugins/plugin_video.py | 15 ++-- tuned/plugins/plugin_vm.py | 15 ++-- tuned/units/manager.py | 2 +- 34 files changed, 346 insertions(+), 213 deletions(-) diff --git a/profiles/openshift/tuned.conf b/profiles/openshift/tuned.conf index 197850c52..6c30c2a49 100644 --- a/profiles/openshift/tuned.conf +++ b/profiles/openshift/tuned.conf @@ -33,4 +33,4 @@ vm.max_map_count=262144 # see rhbz#1979352; exclude containers from aligning to house keeping CPUs cgroup_ps_blacklist=/kubepods\.slice/ # workaround for rhbz#1921738 -runtime=0 +dynamic=0 diff --git a/tests/beakerlib/Traceback-caused-by-scheduler-plugin-with/runtest.sh b/tests/beakerlib/Traceback-caused-by-scheduler-plugin-with/runtest.sh index 64de57202..782152ebe 100755 --- a/tests/beakerlib/Traceback-caused-by-scheduler-plugin-with/runtest.sh +++ b/tests/beakerlib/Traceback-caused-by-scheduler-plugin-with/runtest.sh @@ -42,7 +42,7 @@ rlJournalStart rlRun "pushd /etc/tuned/test-profile" cat << EOF > tuned.conf [scheduler] -runtime=0 +dynamic=0 EOF rlRun "popd" diff --git a/tuned-main.conf b/tuned-main.conf index 86bca4d02..5ff27153f 100644 --- a/tuned-main.conf +++ b/tuned-main.conf @@ -7,7 +7,12 @@ daemon = 1 # Dynamically tune devices, if disabled only static tuning will be used. -dynamic_tuning = 0 +dynamic_tuning = 1 + +# A list of plugins to allow dynamic tuning for. The "dynamic_tuning" +# option must be enabled for this to have any effect. If not set, all +# plugins are allowed to perform dynamic tuning. +dynamic_plugins = scheduler # How long to sleep before checking for events (in seconds) # higher number means lower overhead but longer response time. diff --git a/tuned/consts.py b/tuned/consts.py index 965068a3b..4a05f975b 100644 --- a/tuned/consts.py +++ b/tuned/consts.py @@ -103,6 +103,7 @@ # (see configobj for methods, default is get for string) CFG_DAEMON = "daemon" CFG_DYNAMIC_TUNING = "dynamic_tuning" +CFG_DYNAMIC_PLUGINS = "dynamic_plugins" CFG_SLEEP_INTERVAL = "sleep_interval" CFG_UPDATE_INTERVAL = "update_interval" CFG_RECOMMEND_COMMAND = "recommend_command" diff --git a/tuned/daemon/application.py b/tuned/daemon/application.py index a7400cfee..215cbabd4 100644 --- a/tuned/daemon/application.py +++ b/tuned/daemon/application.py @@ -28,10 +28,6 @@ def __init__(self, profile_name = None, config = None): storage_factory = storage.Factory(storage_provider) self.config = GlobalConfig() if config is None else config - if self.config.get_bool(consts.CFG_DYNAMIC_TUNING): - log.info("dynamic tuning is enabled (can be overridden in plugins)") - else: - log.info("dynamic tuning is globally disabled") monitors_repository = monitors.Repository() udev_buffer_size = self.config.get_size("udev_buffer_size", consts.CFG_DEF_UDEV_BUFFER_SIZE) @@ -53,6 +49,30 @@ def __init__(self, profile_name = None, config = None): profile_locator = profiles.Locator(self.config.get_list(consts.CFG_PROFILE_DIRS, consts.CFG_DEF_PROFILE_DIRS)) profile_loader = profiles.Loader(profile_locator, profile_factory, profile_merger, self.config, self.variables) + if not self.config.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING): + log.info("dynamic tuning is globally disabled") + self.config.set(consts.CFG_DYNAMIC_PLUGINS, []) + else: + all_plugins = {p.name(): p for p in plugins_repository.load_all_plugins()} + all_dynamic_plugins = {name: p for name, p in all_plugins.items() if p.supports_dynamic_tuning()} + enabled_dynamic_plugins = {} + for name in self.config.get_list(consts.CFG_DYNAMIC_PLUGINS, all_dynamic_plugins.keys()): + if name not in all_plugins: + log.warn("Configuring dynamic tuning: Plugin '%s' does not exist" % name) + continue + if name not in all_dynamic_plugins: + log.warn("Configuring dynamic tuning: Plugin '%s' does not support dynamic tuning" % name) + continue + enabled_dynamic_plugins[name] = all_plugins[name] + self.config.set(consts.CFG_DYNAMIC_PLUGINS, enabled_dynamic_plugins.values()) + if set(enabled_dynamic_plugins.keys()) == set(all_dynamic_plugins.keys()): + log.info("dynamic tuning is enabled for all plugins which support it") + elif len(enabled_dynamic_plugins) == 0: + log.info("dynamic tuning is disabled for all plugins") + self.config.set(consts.CFG_DYNAMIC_TUNING, False) + else: + log.info("dynamic tuning is enabled for plugins: %s" % ", ".join(enabled_dynamic_plugins.keys())) + self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config, self) self._controller = controller.Controller(self._daemon, self.config) diff --git a/tuned/daemon/controller.py b/tuned/daemon/controller.py index 6a59a1d86..ab98e1ca5 100644 --- a/tuned/daemon/controller.py +++ b/tuned/daemon/controller.py @@ -290,7 +290,7 @@ def get_all_plugins(self, caller = None): return False plugins = {} for plugin_class in self._daemon.get_all_plugins(): - plugin_name = plugin_class.__module__.split(".")[-1].split("_", 1)[1] + plugin_name = plugin_class.name() conf_options = plugin_class._get_config_options() plugins[plugin_name] = {} for key, val in conf_options.items(): @@ -360,10 +360,10 @@ def instance_acquire_devices(self, devices, instance_name, caller = None): devs -= devs_moving log.info("Moving devices '%s' from instance '%s' to instance '%s'." % (str(devs_moving), instance.name, instance_target.name)) - if (instance.plugin.name != instance_target.plugin.name): + if (instance.plugin.name() != instance_target.plugin.name()): rets = "Target instance '%s' is of type '%s', but devices '%s' are currently handled by " \ "instance '%s' which is of type '%s'." % (instance_target.name, - instance_target.plugin.name, str(devs_moving), instance.name, instance.plugin.name) + instance_target.plugin.name(), str(devs_moving), instance.name, instance.plugin.name()) log.error(rets) return (False, rets) instance.plugin._remove_devices_nocheck(instance, devs_moving) @@ -394,8 +394,8 @@ def get_instances(self, plugin_name, caller = None): return (False, rets, []) instances = filter(lambda instance: instance.active, self._daemon._unit_manager.instances) if plugin_name != "": - instances = filter(lambda instance: instance.plugin.name == plugin_name, instances) - return (True, "OK", list(map(lambda instance: (instance.name, instance.plugin.name), instances))) + instances = filter(lambda instance: instance.plugin.name() == plugin_name, instances) + return (True, "OK", list(map(lambda instance: (instance.name, instance.plugin.name()), instances))) @exports.export("s", "(bsas)") def instance_get_devices(self, instance_name, caller = None): diff --git a/tuned/daemon/daemon.py b/tuned/daemon/daemon.py index 81582d05d..e1d6d9f5c 100644 --- a/tuned/daemon/daemon.py +++ b/tuned/daemon/daemon.py @@ -19,27 +19,28 @@ def __init__(self, unit_manager, profile_loader, profile_names=None, config=None self._daemon = consts.CFG_DEF_DAEMON self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL) self._update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL) - self._dynamic_tuning = consts.CFG_DEF_DYNAMIC_TUNING self._recommend_command = True self._rollback = consts.CFG_DEF_ROLLBACK + dynamic_plugins = [] if config is not None: self._daemon = config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON) self._sleep_interval = int(config.get(consts.CFG_SLEEP_INTERVAL, consts.CFG_DEF_SLEEP_INTERVAL)) self._update_interval = int(config.get(consts.CFG_UPDATE_INTERVAL, consts.CFG_DEF_UPDATE_INTERVAL)) - self._dynamic_tuning = config.get_bool(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING) self._recommend_command = config.get_bool(consts.CFG_RECOMMEND_COMMAND, consts.CFG_DEF_RECOMMEND_COMMAND) self._rollback = config.get(consts.CFG_ROLLBACK, consts.CFG_DEF_ROLLBACK) + dynamic_plugins = config.get(consts.CFG_DYNAMIC_PLUGINS, []) self._application = application + self._periodic_tuning = any(plugin.uses_periodic_tuning() for plugin in dynamic_plugins) if self._sleep_interval <= 0: self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL) if self._update_interval == 0: - self._dynamic_tuning = False + self._periodic_tuning = False elif self._update_interval < self._sleep_interval: self._update_interval = self._sleep_interval self._sleep_cycles = self._update_interval // self._sleep_interval - log.info("using sleep interval of %d second(s)" % self._sleep_interval) - if self._dynamic_tuning: - log.info("dynamic tuning is enabled (can be overridden by plugins)") + if self._periodic_tuning: + log.info("using sleep interval of %d second(s)" % self._sleep_interval) + log.info("periodic tuning is enabled") log.info("using update interval of %d second(s) (%d times of the sleep interval)" % (self._sleep_cycles * self._sleep_interval, self._sleep_cycles)) self._profile_recommender = ProfileRecommender(is_hardcoded = not self._recommend_command) @@ -215,7 +216,7 @@ def _thread_code(self): # For more details see TuneD rhbz#917587. _sleep_cnt = self._sleep_cycles while not self._cmd.wait(self._terminate, self._sleep_interval): - if self._dynamic_tuning: + if self._periodic_tuning: _sleep_cnt -= 1 if _sleep_cnt <= 0: _sleep_cnt = self._sleep_cycles diff --git a/tuned/plugins/base.py b/tuned/plugins/base.py index 8eaf48ada..ae0d0dc02 100644 --- a/tuned/plugins/base.py +++ b/tuned/plugins/base.py @@ -49,9 +49,21 @@ def init_devices(self): self._init_devices() self._devices_inited = True - @property - def name(self): - return self.__class__.__module__.split(".")[-1].split("_", 1)[1] + @classmethod + def name(cls): + return cls.__module__.split(".")[-1].split("_", 1)[1] + + @classmethod + def supports_static_tuning(cls): + raise NotImplementedError() + + @classmethod + def supports_dynamic_tuning(cls): + raise NotImplementedError() + + @classmethod + def uses_periodic_tuning(cls): + raise NotImplementedError() # # Plugin configuration manipulation and helpers. @@ -74,8 +86,10 @@ def _get_config_options_used_by_dynamic(self): def _get_effective_options(self, options): """Merge provided options with plugin default options.""" - # TODO: _has_dynamic_options is a hack effective = self._get_config_options().copy() + if self.supports_dynamic_tuning(): + effective["dynamic"] = True + # TODO: _has_dynamic_options is a hack for key in options: if key in effective or self._has_dynamic_options: effective[key] = options[key] @@ -118,13 +132,13 @@ def destroy_instance(self, instance): def initialize_instance(self, instance): """Initialize an instance.""" - log.debug("initializing instance %s (%s)" % (instance.name, self.name)) + log.debug("initializing instance %s (%s)" % (instance.name, self.name())) self._instance_init(instance) def destroy_instances(self): """Destroy all instances.""" for instance in list(self._instances.values()): - log.debug("destroying instance %s (%s)" % (instance.name, self.name)) + log.debug("destroying instance %s (%s)" % (instance.name, self.name())) self._destroy_instance(instance) self._instances.clear() @@ -133,10 +147,13 @@ def _destroy_instance(self, instance): self._instance_cleanup(instance) def _instance_init(self, instance): - raise NotImplementedError() + instance._static_tuning_enabled = self.supports_static_tuning() + instance._dynamic_tuning_enabled = self.supports_dynamic_tuning() \ + and self.__class__ in self._global_cfg.get(consts.CFG_DYNAMIC_PLUGINS) \ + and instance.options["dynamic"] def _instance_cleanup(self, instance): - raise NotImplementedError() + pass # # Devices handling @@ -158,7 +175,7 @@ def _get_matching_devices(self, instance, devices): else: udev_devices = self._get_device_objects(devices) if udev_devices is None: - log.error("Plugin '%s' does not support the 'devices_udev_regex' option", self.name) + log.error("Plugin '%s' does not support the 'devices_udev_regex' option", self.name()) return set() udev_devices = self._device_matcher_udev.match_list(instance.devices_udev_regex, udev_devices) return set([x.sys_name for x in udev_devices]) @@ -174,8 +191,8 @@ def assign_free_devices(self, instance): log.warn("instance %s: no matching devices available" % instance.name) else: name = instance.name - if instance.name != self.name: - name += " (%s)" % self.name + if instance.name != self.name(): + name += " (%s)" % self.name() log.info("instance %s: assigning devices %s" % (name, ", ".join(to_assign))) instance.assigned_devices.update(to_assign) # cannot use |= self._assigned_devices |= to_assign @@ -254,7 +271,7 @@ def instance_apply_tuning(self, instance): if not instance.active: return - if instance.has_static_tuning: + if instance.static_tuning_enabled: self._call_device_script(instance, instance.script_pre, "apply", instance.assigned_devices) self._instance_pre_static(instance, True) @@ -262,7 +279,7 @@ def instance_apply_tuning(self, instance): self._instance_post_static(instance, True) self._call_device_script(instance, instance.script_post, "apply", instance.assigned_devices) - if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING): + if instance.dynamic_tuning_enabled: self._instance_init_dynamic(instance) self._run_for_each_device(instance, self._instance_apply_dynamic, instance.assigned_devices) instance.processed_devices.update(instance.assigned_devices) @@ -279,7 +296,7 @@ def instance_verify_tuning(self, instance, ignore_missing): log.error("BUG: Some devices have not been tuned: %s" % ", ".join(instance.assigned_devices)) devices = instance.processed_devices.copy() - if instance.has_static_tuning: + if instance.static_tuning_enabled: if self._call_device_script(instance, instance.script_pre, "verify", devices) == False: return False if self._instance_verify_static(instance, ignore_missing, devices) == False: @@ -296,7 +313,7 @@ def instance_update_tuning(self, instance): """ if not instance.active: return - if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING): + if instance.dynamic_tuning_enabled and self.uses_periodic_tuning(): self._run_for_each_device(instance, self._instance_update_dynamic, instance.processed_devices.copy()) def instance_unapply_tuning(self, instance, rollback = consts.ROLLBACK_SOFT): @@ -306,9 +323,10 @@ def instance_unapply_tuning(self, instance, rollback = consts.ROLLBACK_SOFT): if rollback == consts.ROLLBACK_NONE: return - if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING): + if instance.dynamic_tuning_enabled: self._run_for_each_device(instance, self._instance_unapply_dynamic, instance.processed_devices) - if instance.has_static_tuning: + self._instance_deinit_dynamic(instance) + if instance.static_tuning_enabled: self._call_device_script(instance, instance.script_post, "unapply", instance.processed_devices, rollback = rollback) @@ -337,14 +355,17 @@ def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT): def _instance_init_dynamic(self, instance): pass + def _instance_deinit_dynamic(self, instance): + pass + def _instance_apply_dynamic(self, instance, device): for option in [opt for opt in self._options_used_by_dynamic if self._storage_get(instance, self._commands[opt], device) is None]: self._check_and_save_value(instance, self._commands[option], device) - - self._instance_update_dynamic(instance, device) + if self.uses_periodic_tuning(): + self._instance_update_dynamic(instance, device) def _instance_unapply_dynamic(self, instance, device): - raise NotImplementedError() + pass def _instance_update_dynamic(self, instance, device): raise NotImplementedError() diff --git a/tuned/plugins/hotplug.py b/tuned/plugins/hotplug.py index 9e392a704..e44de4b3e 100644 --- a/tuned/plugins/hotplug.py +++ b/tuned/plugins/hotplug.py @@ -103,10 +103,10 @@ def _remove_devices_nocheck(self, instance, device_names): def _added_device_apply_tuning(self, instance, device_name): self._execute_all_device_commands(instance, [device_name]) - if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING): + if instance.dynamic_tuning_enabled: self._instance_apply_dynamic(instance, device_name) def _removed_device_unapply_tuning(self, instance, device_name): - if instance.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING): + if instance.dynamic_tuning_enabled: self._instance_unapply_dynamic(instance, device_name) self._cleanup_all_device_commands(instance, [device_name], remove = True) diff --git a/tuned/plugins/instance/instance.py b/tuned/plugins/instance/instance.py index 1e286729d..8b70c7a68 100644 --- a/tuned/plugins/instance/instance.py +++ b/tuned/plugins/instance/instance.py @@ -14,8 +14,8 @@ def __init__(self, plugin, name, devices_expression, devices_udev_regex, script_ self._options = options self._active = True - self._has_static_tuning = False - self._has_dynamic_tuning = False + self._static_tuning_enabled = False + self._dynamic_tuning_enabled = False self._assigned_devices = set() self._processed_devices = set() @@ -67,12 +67,12 @@ def options(self): return self._options @property - def has_static_tuning(self): - return self._has_static_tuning + def static_tuning_enabled(self): + return self._static_tuning_enabled @property - def has_dynamic_tuning(self): - return self._has_dynamic_tuning + def dynamic_tuning_enabled(self): + return self._dynamic_tuning_enabled # methods diff --git a/tuned/plugins/plugin_acpi.py b/tuned/plugins/plugin_acpi.py index 38eca6829..99a860016 100644 --- a/tuned/plugins/plugin_acpi.py +++ b/tuned/plugins/plugin_acpi.py @@ -37,15 +37,16 @@ def __init__(self, *args, **kwargs): super(ACPIPlugin, self).__init__(*args, **kwargs) @classmethod - def _get_config_options(cls): - return {"platform_profile": None} + def supports_static_tuning(cls): + return True - def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False + @classmethod + def supports_dynamic_tuning(cls): + return False - def _instance_cleanup(self, instance): - pass + @classmethod + def _get_config_options(cls): + return {"platform_profile": None} @classmethod def _platform_profile_choices_path(cls): diff --git a/tuned/plugins/plugin_audio.py b/tuned/plugins/plugin_audio.py index eee932cb9..e25f0952f 100644 --- a/tuned/plugins/plugin_audio.py +++ b/tuned/plugins/plugin_audio.py @@ -37,6 +37,14 @@ class AudioPlugin(hotplug.Plugin): ==== """ + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _init_devices(self): self._devices_supported = True self._assigned_devices = set() @@ -47,13 +55,6 @@ def _init_devices(self): if module_name in ["snd_hda_intel", "snd_ac97_codec"]: self._free_devices.add(module_name) - def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False - - def _instance_cleanup(self, instance): - pass - def _device_module_name(self, device): try: return device.parent.driver diff --git a/tuned/plugins/plugin_bootloader.py b/tuned/plugins/plugin_bootloader.py index 1b79c3813..3a16341ad 100644 --- a/tuned/plugins/plugin_bootloader.py +++ b/tuned/plugins/plugin_bootloader.py @@ -193,9 +193,16 @@ def __init__(self, *args, **kwargs): super(BootloaderPlugin, self).__init__(*args, **kwargs) self._cmd = commands() + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True + super(BootloaderPlugin, self)._instance_init(instance) # controls grub2_cfg rewrites in _instance_post_static self.update_grub2_cfg = False self._skip_grub_config_val = False @@ -208,9 +215,6 @@ def _instance_init(self, instance): self._rpm_ostree = self._rpm_ostree_status() is not None - def _instance_cleanup(self, instance): - pass - @classmethod def _get_config_options(cls): return { diff --git a/tuned/plugins/plugin_cpu.py b/tuned/plugins/plugin_cpu.py index 9475854f5..0a7aa2c5b 100644 --- a/tuned/plugins/plugin_cpu.py +++ b/tuned/plugins/plugin_cpu.py @@ -209,6 +209,18 @@ def __init__(self, *args, **kwargs): self._flags = None + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return True + + @classmethod + def uses_periodic_tuning(cls): + return True + def _init_devices(self): self._devices_supported = True self._free_devices = set() @@ -315,8 +327,7 @@ def _check_cpu_can_change_governor(self, device): return True def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False + super(CPULatencyPlugin, self)._instance_init(instance) instance._load_monitor = None # only the first instance of the plugin can control the latency @@ -329,12 +340,13 @@ def _instance_init(self, instance): self._has_pm_qos = False self._latency = None - if instance.options["force_latency"] is None and instance.options["pm_qos_resume_latency_us"] is None: - instance._has_dynamic_tuning = True + if not instance.options["force_latency"] is None or not instance.options["pm_qos_resume_latency_us"] is None: + instance._dynamic_tuning_enabled = False self._check_arch() else: instance._first_instance = False + instance._dynamic_tuning_enabled = False log.info("Latency settings from non-first CPU plugin instance '%s' will be ignored." % instance.name) try: @@ -414,9 +426,6 @@ def _instance_update_dynamic(self, instance, device): else: self._set_latency(instance.options["latency_low"]) - def _instance_unapply_dynamic(self, instance, device): - pass - def _str2int(self, s): try: return int(s) diff --git a/tuned/plugins/plugin_disk.py b/tuned/plugins/plugin_disk.py index 1438e3542..bc7c97750 100644 --- a/tuned/plugins/plugin_disk.py +++ b/tuned/plugins/plugin_disk.py @@ -95,6 +95,18 @@ def __init__(self, *args, **kwargs): self._load_smallest = 0.01 self._cmd = commands() + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return True + + @classmethod + def uses_periodic_tuning(cls): + return False + def _init_devices(self): super(DiskPlugin, self)._init_devices() self._devices_supported = True @@ -158,7 +170,6 @@ def _removed_device_unapply_tuning(self, instance, device_name): @classmethod def _get_config_options(cls): return { - "dynamic" : True, # FIXME: do we want this default? "elevator" : None, "apm" : None, "spindown" : None, @@ -175,13 +186,10 @@ def _get_config_options_used_by_dynamic(cls): ] def _instance_init(self, instance): - instance._has_static_tuning = True - + super(DiskPlugin, self)._instance_init(instance) self._apm_errcnt = 0 self._spindown_errcnt = 0 - instance._load_monitor = None - instance._has_dynamic_tuning = self._option_bool(instance.options["dynamic"]) def _instance_cleanup(self, instance): if instance._load_monitor is not None: @@ -320,9 +328,6 @@ def _instance_apply_dynamic(self, instance, device): else: super(DiskPlugin, self)._instance_apply_dynamic(instance, device) - def _instance_unapply_dynamic(self, instance, device): - pass - def _sysfs_path(self, device, suffix, prefix = "/sys/block/"): if "/" in device: dev = os.path.join(prefix, device.replace("/", "!"), suffix) diff --git a/tuned/plugins/plugin_eeepc_she.py b/tuned/plugins/plugin_eeepc_she.py index d292e225d..2657b03a1 100644 --- a/tuned/plugins/plugin_eeepc_she.py +++ b/tuned/plugins/plugin_eeepc_she.py @@ -36,6 +36,18 @@ def __init__(self, *args, **kwargs): raise exceptions.NotSupportedPluginException("Plugin is not supported on your hardware.") super(EeePCSHEPlugin, self).__init__(*args, **kwargs) + @classmethod + def supports_static_tuning(cls): + return False + + @classmethod + def supports_dynamic_tuning(cls): + return True + + @classmethod + def uses_periodic_tuning(cls): + return False + @classmethod def _get_config_options(self): return { @@ -46,8 +58,7 @@ def _get_config_options(self): } def _instance_init(self, instance): - instance._has_static_tuning = False - instance._has_dynamic_tuning = True + super(EeePCSHEPlugin, self)._instance_init(instance) instance._she_mode = None instance._load_monitor = None diff --git a/tuned/plugins/plugin_irqbalance.py b/tuned/plugins/plugin_irqbalance.py index d8e9e59fb..4f0e934cd 100644 --- a/tuned/plugins/plugin_irqbalance.py +++ b/tuned/plugins/plugin_irqbalance.py @@ -33,12 +33,13 @@ def __init__(self, *args, **kwargs): super(IrqbalancePlugin, self).__init__(*args, **kwargs) self._cpus = perf.cpu_map() - def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True + @classmethod + def supports_static_tuning(cls): + return True - def _instance_cleanup(self, instance): - pass + @classmethod + def supports_dynamic_tuning(cls): + return False @classmethod def _get_config_options(cls): diff --git a/tuned/plugins/plugin_modules.py b/tuned/plugins/plugin_modules.py index eb815b2ef..11ee75746 100644 --- a/tuned/plugins/plugin_modules.py +++ b/tuned/plugins/plugin_modules.py @@ -53,14 +53,18 @@ def __init__(self, *args, **kwargs): self._has_dynamic_options = True self._cmd = commands() + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True + super(ModulesPlugin, self)._instance_init(instance) instance._modules = instance.options - def _instance_cleanup(self, instance): - pass - def _reload_modules(self, modules): for module in modules: retcode, out = self._cmd.execute(["modprobe", "-r", module]) diff --git a/tuned/plugins/plugin_mounts.py b/tuned/plugins/plugin_mounts.py index e64111cd8..81b933797 100644 --- a/tuned/plugins/plugin_mounts.py +++ b/tuned/plugins/plugin_mounts.py @@ -20,6 +20,14 @@ class MountsPlugin(base.Plugin): systems (ext) are supported by this plug-in. """ + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + @classmethod def _generate_mountpoint_topology(cls): """ @@ -68,13 +76,6 @@ def _get_config_options(self): "disable_barriers": None, } - def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True - - def _instance_cleanup(self, instance): - pass - def _get_device_cache_type(self, device): """ Get device cache type. This will work only for devices on SCSI kernel subsystem. diff --git a/tuned/plugins/plugin_net.py b/tuned/plugins/plugin_net.py index 521198a16..cab9fb655 100644 --- a/tuned/plugins/plugin_net.py +++ b/tuned/plugins/plugin_net.py @@ -159,6 +159,18 @@ def __init__(self, *args, **kwargs): self._re_ip_link_show = {} self._use_ip = True + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return True + + @classmethod + def uses_periodic_tuning(cls): + return False + def _init_devices(self): self._devices_supported = True self._free_devices = set() @@ -175,11 +187,10 @@ def _get_device_objects(self, devices): return [self._hardware_inventory.get_device("net", x) for x in devices] def _instance_init(self, instance): - instance._has_static_tuning = True + super(NetTuningPlugin, self)._instance_init(instance) instance._load_monitor = None instance._idle = None instance._stats = None - instance._has_dynamic_tuning = self._option_bool(instance.options["dynamic"]) def _instance_cleanup(self, instance): if instance._load_monitor is not None: @@ -270,7 +281,6 @@ def _get_config_options_channels(cls): @classmethod def _get_config_options(cls): return { - "dynamic": True, "wake_on_lan": None, "nf_conntrack_hashsize": None, "features": None, diff --git a/tuned/plugins/plugin_rtentsk.py b/tuned/plugins/plugin_rtentsk.py index 31e216778..870c5dd0a 100644 --- a/tuned/plugins/plugin_rtentsk.py +++ b/tuned/plugins/plugin_rtentsk.py @@ -17,13 +17,19 @@ class RTENTSKPlugin(base.Plugin): socket ourselves the static key is kept enabled). """ + @classmethod + def supports_dynamic_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False + super(RTENTSKPlugin, self)._instance_init(instance) # SO_TIMESTAMP nor SOF_TIMESTAMPING_OPT_TX_SWHW is defined by # the socket class - SO_TIMESTAMP = 29 # see include/uapi/asm-generic/socket.h #define SO_TIMESTAMP 0x4012 # parisc! SOF_TIMESTAMPING_OPT_TX_SWHW = (1<<14) # see include/uapi/linux/net_tstamp.h diff --git a/tuned/plugins/plugin_scheduler.py b/tuned/plugins/plugin_scheduler.py index 85d615159..0485d90b9 100644 --- a/tuned/plugins/plugin_scheduler.py +++ b/tuned/plugins/plugin_scheduler.py @@ -273,7 +273,7 @@ class SchedulerPlugin(base.Plugin): processes are not processed by the scheduler plug-in. + The CPU overhead of the scheduler plugin can be mitigated by using - the scheduler [option]`runtime` option and setting it to `0`. This + the scheduler [option]`dynamic` option and setting it to `0`. This will completely disable the dynamic scheduler functionality and the perf events will not be monitored and acted upon. The disadvantage ot this approach is the procees/thread tuning will be done only at @@ -283,7 +283,7 @@ class SchedulerPlugin(base.Plugin): ==== ---- [scheduler] - runtime=0 + dynamic=0 isolated_cores=1,3 ---- ==== @@ -459,6 +459,18 @@ def __init__(self, monitor_repository, storage_factory, hardware_inventory, devi except AttributeError: self._scheduler_utils = SchedulerUtilsSchedutils() + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return True + + @classmethod + def uses_periodic_tuning(cls): + return False + def _calc_mmap_pages(self, mmap_pages): if mmap_pages is None: return None @@ -472,13 +484,8 @@ def _calc_mmap_pages(self, mmap_pages): return int(2 ** math.ceil(math.log(mp, 2))) def _instance_init(self, instance): + super(SchedulerPlugin, self)._instance_init(instance) instance._evlist = None - instance._has_dynamic_tuning = False - instance._has_static_tuning = True - # this is hack, runtime_tuning should be covered by dynamic_tuning configuration - # TODO: add per plugin dynamic tuning configuration and use dynamic_tuning configuration - # instead of runtime_tuning - instance._runtime_tuning = True # FIXME: do we want to do this here? # recover original values in case of crash @@ -503,42 +510,44 @@ def _instance_init(self, instance): instance._scheduler = instance.options perf_mmap_pages_raw = self._variables.expand(instance.options["perf_mmap_pages"]) - perf_mmap_pages = self._calc_mmap_pages(perf_mmap_pages_raw) - if perf_mmap_pages == 0: + instance._perf_mmap_pages = self._calc_mmap_pages(perf_mmap_pages_raw) + if instance._perf_mmap_pages == 0: log.error("Invalid 'perf_mmap_pages' value specified: '%s', using default kernel value" % perf_mmap_pages_raw) - perf_mmap_pages = None - if perf_mmap_pages is not None and str(perf_mmap_pages) != perf_mmap_pages_raw: + instance._perf_mmap_pages = None + if instance._perf_mmap_pages is not None and str(instance._perf_mmap_pages) != perf_mmap_pages_raw: log.info("'perf_mmap_pages' value has to be power of two, specified: '%s', using: '%d'" % - (perf_mmap_pages_raw, perf_mmap_pages)) + (perf_mmap_pages_raw, instance._perf_mmap_pages)) for k in instance._scheduler: instance._scheduler[k] = self._variables.expand(instance._scheduler[k]) - if self._cmd.get_bool(instance._scheduler.get("runtime", 1)) == "0": - instance._runtime_tuning = False - instance._terminate = threading.Event() - if self._daemon and instance._runtime_tuning: - try: - instance._threads = perf.thread_map() - evsel = perf.evsel(type = perf.TYPE_SOFTWARE, - config = perf.COUNT_SW_DUMMY, - task = 1, comm = 1, mmap = 0, freq = 0, - wakeup_events = 1, watermark = 1, - sample_type = perf.SAMPLE_TID | perf.SAMPLE_CPU) - evsel.open(cpus = self._cpus, threads = instance._threads) - instance._evlist = perf.evlist(self._cpus, instance._threads) - instance._evlist.add(evsel) - if perf_mmap_pages is None: - instance._evlist.mmap() - else: - instance._evlist.mmap(pages = perf_mmap_pages) - # no perf - except: - instance._runtime_tuning = False def _instance_cleanup(self, instance): if instance._evlist: for fd in instance._evlist.get_pollfd(): os.close(fd.name) + def _instance_init_dynamic(self, instance): + super(SchedulerPlugin, self)._instance_init_dynamic(instance) + instance._terminate = threading.Event() + try: + instance._threads = perf.thread_map() + evsel = perf.evsel(type = perf.TYPE_SOFTWARE, + config = perf.COUNT_SW_DUMMY, + task = 1, comm = 1, mmap = 0, freq = 0, + wakeup_events = 1, watermark = 1, + sample_type = perf.SAMPLE_TID | perf.SAMPLE_CPU) + evsel.open(cpus = self._cpus, threads = instance._threads) + instance._evlist = perf.evlist(self._cpus, instance._threads) + instance._evlist.add(evsel) + if instance._perf_mmap_pages is None: + instance._evlist.mmap() + else: + instance._evlist.mmap(pages = instance._perf_mmap_pages) + instance._thread = threading.Thread(target = self._thread_code, args = [instance]) + instance._thread.start() + # no perf + except: + instance._dynamic_tuning_enabled = False + @classmethod def _get_config_options(cls): return { @@ -942,7 +951,7 @@ def _instance_apply_static(self, instance): and len(vals) == 5] sched_cfg = sorted(buf, key=lambda option_vals: option_vals[1][0]) sched_all = dict() - # for runtime tuning + # for dynamic tuning instance._sched_lookup = {} for option, (rule_prio, scheduler, priority, affinity, regex) \ in sched_cfg: @@ -966,9 +975,6 @@ def _instance_apply_static(self, instance): priority, affinity) self._storage.set(self._scheduler_storage_key, self._scheduler_original) - if self._daemon and instance._runtime_tuning: - instance._thread = threading.Thread(target = self._thread_code, args = [instance]) - instance._thread.start() def _restore_ps_affinity(self): try: @@ -1013,9 +1019,6 @@ def _cgroup_cleanup_tasks(self): def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT): super(SchedulerPlugin, self)._instance_unapply_static(instance, rollback) - if self._daemon and instance._runtime_tuning: - instance._terminate.set() - instance._thread.join() self._restore_ps_affinity() self._cgroup_restore_affinity() self._cgroup_cleanup_tasks() @@ -1024,6 +1027,10 @@ def _instance_unapply_static(self, instance, rollback = consts.ROLLBACK_SOFT): if self._cgroup_mount_point_init: self._cgroup_finalize() + def _instance_deinit_dynamic(self, instance): + instance._terminate.set() + instance._thread.join() + def _cgroup_verify_affinity_one(self, cgroup, affinity): log.debug("Verifying cgroup '%s' affinity" % cgroup) path = "%s/%s/%s" % (self._cgroup_mount_point, cgroup, "cpuset.cpus") diff --git a/tuned/plugins/plugin_script.py b/tuned/plugins/plugin_script.py index ab605e429..243f67fa4 100644 --- a/tuned/plugins/plugin_script.py +++ b/tuned/plugins/plugin_script.py @@ -57,9 +57,16 @@ def _get_config_options(self): "script" : None, } + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False + super(ScriptPlugin, self)._instance_init(instance) if instance.options["script"] is not None: # FIXME: this hack originated from profiles merger assert isinstance(instance.options["script"], list) @@ -67,9 +74,6 @@ def _instance_init(self, instance): else: instance._scripts = [] - def _instance_cleanup(self, instance): - pass - def _call_scripts(self, scripts, arguments): ret = True for script in scripts: diff --git a/tuned/plugins/plugin_scsi_host.py b/tuned/plugins/plugin_scsi_host.py index a230a1286..2baff6c64 100644 --- a/tuned/plugins/plugin_scsi_host.py +++ b/tuned/plugins/plugin_scsi_host.py @@ -36,6 +36,14 @@ def __init__(self, *args, **kwargs): self._cmd = commands() + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _init_devices(self): super(SCSIHostPlugin, self)._init_devices() self._devices_supported = True @@ -75,13 +83,6 @@ def _get_config_options(cls): "alpm" : None, } - def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False - - def _instance_cleanup(self, instance): - pass - def _get_alpm_policy_file(self, device): return os.path.join("/sys/class/scsi_host/", str(device), "link_power_management_policy") diff --git a/tuned/plugins/plugin_selinux.py b/tuned/plugins/plugin_selinux.py index 313b9c4a9..84a34f9b4 100644 --- a/tuned/plugins/plugin_selinux.py +++ b/tuned/plugins/plugin_selinux.py @@ -33,6 +33,14 @@ class SelinuxPlugin(base.Plugin): ==== """ + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + @classmethod def _get_selinux_path(self): path = "/sys/fs/selinux" @@ -56,13 +64,6 @@ def _get_config_options(self): "avc_cache_threshold" : None, } - def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False - - def _instance_cleanup(self, instance): - pass - @command_set("avc_cache_threshold") def _set_avc_cache_threshold(self, value, sim, remove): if value is None: diff --git a/tuned/plugins/plugin_service.py b/tuned/plugins/plugin_service.py index 2f2f20eea..9a8a29caa 100644 --- a/tuned/plugins/plugin_service.py +++ b/tuned/plugins/plugin_service.py @@ -215,6 +215,14 @@ def __init__(self, *args, **kwargs): self._has_dynamic_options = True self._init_handler = self._detect_init_system() + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _check_cmd(self, command): (retcode, out) = cmd.execute(command, no_errors = [0]) return retcode == 0 @@ -254,17 +262,13 @@ def _parse_service_options(self, name, val): return service def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True + super(ServicePlugin, self)._instance_init(instance) self._services = collections.OrderedDict([(option[8:], self._parse_service_options(option[8:], self._variables.expand(value))) for option, value in instance.options.items() if option[:8] == "service." and len(option) > 8]) instance._services_original = {} - def _instance_cleanup(self, instance): - pass - def _process_service(self, name, start, enable, runlevel): if start: self._init_handler.start(name) diff --git a/tuned/plugins/plugin_sysctl.py b/tuned/plugins/plugin_sysctl.py index 96854fd08..d0d045d09 100644 --- a/tuned/plugins/plugin_sysctl.py +++ b/tuned/plugins/plugin_sysctl.py @@ -44,10 +44,16 @@ def __init__(self, *args, **kwargs): self._has_dynamic_options = True self._cmd = commands() - def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _instance_init(self, instance): + super(SysctlPlugin, self)._instance_init(instance) # FIXME: do we want to do this here? # recover original values in case of crash storage_key = self._storage_key(instance.name) diff --git a/tuned/plugins/plugin_sysfs.py b/tuned/plugins/plugin_sysfs.py index 4f14e2add..1a751dd7d 100644 --- a/tuned/plugins/plugin_sysfs.py +++ b/tuned/plugins/plugin_sysfs.py @@ -41,16 +41,20 @@ def __init__(self, *args, **kwargs): self._has_dynamic_options = True self._cmd = commands() + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True + super(SysfsPlugin, self)._instance_init(instance) instance._sysfs = dict([(os.path.normpath(key_value[0]), key_value[1]) for key_value in list(instance.options.items())]) instance._sysfs_original = {} - def _instance_cleanup(self, instance): - pass - def _instance_apply_static(self, instance): for key, value in list(instance._sysfs.items()): v = self._variables.expand(value) diff --git a/tuned/plugins/plugin_systemd.py b/tuned/plugins/plugin_systemd.py index 49304ae48..1f9135748 100644 --- a/tuned/plugins/plugin_systemd.py +++ b/tuned/plugins/plugin_systemd.py @@ -39,12 +39,13 @@ def __init__(self, *args, **kwargs): super(SystemdPlugin, self).__init__(*args, **kwargs) self._cmd = commands() - def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True + @classmethod + def supports_static_tuning(cls): + return True - def _instance_cleanup(self, instance): - pass + @classmethod + def supports_dynamic_tuning(cls): + return False @classmethod def _get_config_options(cls): diff --git a/tuned/plugins/plugin_uncore.py b/tuned/plugins/plugin_uncore.py index 76af767dd..e19af4d92 100644 --- a/tuned/plugins/plugin_uncore.py +++ b/tuned/plugins/plugin_uncore.py @@ -33,6 +33,14 @@ class UncorePlugin(hotplug.Plugin): ==== """ + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _init_devices(self): self._devices_supported = True self._assigned_devices = set() @@ -55,13 +63,6 @@ def _init_devices(self): log.debug("devices: %s", str(self._free_devices)) - def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False - - def _instance_cleanup(self, instance): - pass - def _get(self, dev_dir, file): sysfs_file = SYSFS_DIR + dev_dir + "/" + file value = cmd.read_file(sysfs_file) diff --git a/tuned/plugins/plugin_usb.py b/tuned/plugins/plugin_usb.py index 159d336f1..30e5eb265 100644 --- a/tuned/plugins/plugin_usb.py +++ b/tuned/plugins/plugin_usb.py @@ -28,6 +28,14 @@ class USBPlugin(base.Plugin): ==== """ + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _init_devices(self): self._devices_supported = True self._free_devices = set() @@ -47,13 +55,6 @@ def _get_config_options(self): "autosuspend" : None, } - def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False - - def _instance_cleanup(self, instance): - pass - def _autosuspend_sysfile(self, device): return "/sys/bus/usb/devices/%s/power/autosuspend" % device diff --git a/tuned/plugins/plugin_video.py b/tuned/plugins/plugin_video.py index a93d60991..3bcf4f80f 100644 --- a/tuned/plugins/plugin_video.py +++ b/tuned/plugins/plugin_video.py @@ -42,6 +42,14 @@ class VideoPlugin(base.Plugin): ==== """ + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + def _init_devices(self): self._devices_supported = True self._free_devices = set() @@ -62,13 +70,6 @@ def _get_config_options(self): "radeon_powersave" : None, } - def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True - - def _instance_cleanup(self, instance): - pass - def _radeon_powersave_files(self, device): return { "method" : "/sys/class/drm/%s/device/power_method" % device, diff --git a/tuned/plugins/plugin_vm.py b/tuned/plugins/plugin_vm.py index e86230b63..048f9a958 100644 --- a/tuned/plugins/plugin_vm.py +++ b/tuned/plugins/plugin_vm.py @@ -34,6 +34,14 @@ class VMPlugin(base.Plugin): link:https://www.kernel.org/doc/Documentation/vm/transhuge.txt[Transparent Hugepage Support]. """ + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + @classmethod def _get_config_options(self): return { @@ -42,13 +50,6 @@ def _get_config_options(self): "transparent_hugepage.defrag" : None, } - def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False - - def _instance_cleanup(self, instance): - pass - @classmethod def _thp_path(self): path = "/sys/kernel/mm/transparent_hugepage" diff --git a/tuned/units/manager.py b/tuned/units/manager.py index 2612c1c4e..7033dedde 100644 --- a/tuned/units/manager.py +++ b/tuned/units/manager.py @@ -131,7 +131,7 @@ def destroy_all(self): instance.plugin.destroy_instance, instance) for plugin in self._plugins: - log.debug("cleaning plugin '%s'" % plugin.name) + log.debug("cleaning plugin '%s'" % plugin.name()) self._try_call("destroy_all", None, plugin.cleanup) del self._plugins[:]