diff --git a/profiles/openshift/tuned.conf b/profiles/openshift/tuned.conf index 197850c5..6c30c2a4 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 d5cce712..5a13b7f0 100755 --- a/tests/beakerlib/Traceback-caused-by-scheduler-plugin-with/runtest.sh +++ b/tests/beakerlib/Traceback-caused-by-scheduler-plugin-with/runtest.sh @@ -43,7 +43,7 @@ rlJournalStart rlRun "pushd $PROFILE_DIR/test-profile" cat << EOF > tuned.conf [scheduler] -runtime=0 +dynamic=0 EOF rlRun "popd" diff --git a/tests/unit/plugins/test_base.py b/tests/unit/plugins/test_base.py index 7f59624c..ca4791de 100644 --- a/tests/unit/plugins/test_base.py +++ b/tests/unit/plugins/test_base.py @@ -169,6 +169,14 @@ def __init__(self,*args,**kwargs): super(DummyPlugin,self).__init__(*args,**kwargs) self.cleaned_instances = [] + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + @classmethod def _get_config_options(self): return {'default_option1':'default_value1',\ @@ -205,6 +213,14 @@ def __init__(self,*args,**kwargs): super(CommandsPlugin,self).__init__(*args,**kwargs) self._size = 'S' + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + @classmethod def _get_config_options(self): """Default configuration options for the plugin.""" diff --git a/tuned-main.conf b/tuned-main.conf index 1f1269f8..edbd49e4 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 48c80f0d..debaa080 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 a7400cfe..d6050cc3 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,8 @@ 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) + self._configure_dynamic_tuning(plugins_repository) + self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config, self) self._controller = controller.Controller(self._daemon, self.config) @@ -71,6 +69,35 @@ def _init_signals(self): self._handle_signal(signal.SIGINT, self._controller.terminate) self._handle_signal(signal.SIGTERM, self._controller.terminate) + def _configure_dynamic_tuning(self, plugins_repository): + # First check if the global `dynamic_tuning` option is set to False, + # disabling dynamic tuning for all plugins + 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, []) + return + # If the global `dynamic_tuning` is True, check the `dynamic_plugins` option, which + # restricts the dynamic tuning to selected plugins only (if present) + 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()} + # If it's not present, we enable dynamic tuning where possible + if self.config.get(consts.CFG_DYNAMIC_PLUGINS) is None: + self.config.set(consts.CFG_DYNAMIC_PLUGINS, all_dynamic_plugins.values()) + log.info("dynamic tuning is enabled for all plugins which support it") + return + # Otherwise only to the specified plugins + enabled_dynamic_plugins = {} + for name in self.config.get_list(consts.CFG_DYNAMIC_PLUGINS): + 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()) + log.info("dynamic tuning is enabled for plugins: %s" % ", ".join(enabled_dynamic_plugins.keys())) + def attach_to_dbus(self, bus_name, object_name, interface_name, namespace): if self._dbus_exporter is not None: raise TunedException("DBus interface is already initialized.") diff --git a/tuned/daemon/controller.py b/tuned/daemon/controller.py index 7ddcd2d6..6f5e5636 100644 --- a/tuned/daemon/controller.py +++ b/tuned/daemon/controller.py @@ -297,7 +297,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(): @@ -371,10 +371,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) @@ -405,8 +405,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 d87d8cd0..b1ab159d 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) @@ -217,7 +218,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 afeb37f8..c7292d6f 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] @@ -119,13 +133,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() @@ -134,10 +148,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 self._option_bool(instance.options["dynamic"]) def _instance_cleanup(self, instance): - raise NotImplementedError() + pass # # Devices handling @@ -159,7 +176,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]) @@ -175,8 +192,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 @@ -255,7 +272,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) @@ -263,7 +280,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) @@ -280,7 +297,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: @@ -297,7 +314,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): @@ -307,9 +324,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) @@ -338,14 +356,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 9e392a70..e44de4b3 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 d789d353..b27dfd95 100644 --- a/tuned/plugins/instance/instance.py +++ b/tuned/plugins/instance/instance.py @@ -15,8 +15,8 @@ def __init__(self, plugin, name, priority, devices_expression, devices_udev_rege self._active = True self._priority = priority - 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() @@ -72,12 +72,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 38eca682..c2c5942e 100644 --- a/tuned/plugins/plugin_acpi.py +++ b/tuned/plugins/plugin_acpi.py @@ -33,19 +33,18 @@ class ACPIPlugin(base.Plugin): ==== -- """ - 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 eee932cb..e25f0952 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 1b79c381..3a16341a 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 648c5e4d..998896fe 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 1438e354..b95c37ba 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 True + 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 d292e225..cd192701 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 True + @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_irq.py b/tuned/plugins/plugin_irq.py index 09684383..236fb378 100644 --- a/tuned/plugins/plugin_irq.py +++ b/tuned/plugins/plugin_irq.py @@ -59,6 +59,14 @@ def __init__(self, monitor_repository, storage_factory, hardware_inventory, devi super(IrqPlugin, self).__init__(monitor_repository, storage_factory, hardware_inventory, device_matcher, device_matcher_udev, plugin_instance_factory, global_cfg, variables) self._irqs = {} + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False + # # plugin-level methods: devices and plugin options # @@ -91,9 +99,6 @@ def _get_config_options(cls): # instance-level methods: implement the Instance interface # def _instance_init(self, instance): - instance._has_static_tuning = True - instance._has_dynamic_tuning = False - affinity = instance.options.get("affinity") affinity_list = self._cmd.cpulist_unpack(affinity) if len(affinity.strip()) == 0: @@ -111,8 +116,6 @@ def _instance_init(self, instance): % (mode, instance.name)) instance.options["mode"] = "set" - def _instance_cleanup(self, instance): - pass def _instance_apply_static(self, instance): log.debug("Applying IRQ affinities (%s)" % instance.name) diff --git a/tuned/plugins/plugin_irqbalance.py b/tuned/plugins/plugin_irqbalance.py index d8e9e59f..4f0e934c 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 fa2d04b1..d53d1449 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 e64111cd..81b93379 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 521198a1..44ec1bc9 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 True + 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 31e21677..870c5dd0 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 85d61515..64cf0cbe 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 Exception: + 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 ab605e42..243f67fa 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 a230a128..2baff6c6 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 313b9c4a..84a34f9b 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 2f2f20ee..9a8a29ca 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 96854fd0..d0d045d0 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 4f14e2ad..1a751dd7 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 49304ae4..1f913574 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 76af767d..e19af4d9 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 159d336f..30e5eb26 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 4bd76ddd..df5a6587 100644 --- a/tuned/plugins/plugin_video.py +++ b/tuned/plugins/plugin_video.py @@ -48,8 +48,13 @@ class VideoPlugin(base.Plugin): but will trade off color accuracy. """ - def __init__(self, *args, **kwargs): - super(VideoPlugin, self).__init__(*args, **kwargs) + @classmethod + def supports_static_tuning(cls): + return True + + @classmethod + def supports_dynamic_tuning(cls): + return False def _init_devices(self): self._devices_supported = True @@ -74,13 +79,6 @@ def _get_config_options(self): "panel_power_savings": None, } - def _instance_init(self, instance): - instance._has_dynamic_tuning = False - instance._has_static_tuning = True - - def _instance_cleanup(self, instance): - pass - def _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 e86230b6..048f9a95 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 51f3490c..2bb44313 100644 --- a/tuned/units/manager.py +++ b/tuned/units/manager.py @@ -133,7 +133,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[:]