1
0
Fork 0

hotplug: do not report ENOENT errors on device remove

It requires slight internal plugin API change, thus 3rd party plugins
needs updating.

Namely the 'command_set' methods for devices were extended by the
'remove' boolean parameter which is set to 'True' on the hotplug remove
event. Then the method should silent the ENOENT errors where
appropriate, because the device interface may be removed (by
kernel/udev) before the method finishes.

Resolves: RHEL-11342

Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
This commit is contained in:
Jaroslav Škarvada 2023-12-06 22:33:39 +01:00
parent 2652d7c29d
commit 2f911b7e02
No known key found for this signature in database
GPG key ID: D8E1C00E076E840B
14 changed files with 127 additions and 89 deletions

View file

@ -211,7 +211,7 @@ class CommandsPlugin(Plugin):
return {'size':'S','device_setting':'101'} return {'size':'S','device_setting':'101'}
@decorators.command_set('size') @decorators.command_set('size')
def _set_size(self, new_size, sim): def _set_size(self, new_size, sim, remove):
self._size = new_size self._size = new_size
return new_size return new_size
@ -220,7 +220,7 @@ class CommandsPlugin(Plugin):
return self._size return self._size
@decorators.command_set('device_setting',per_device = True) @decorators.command_set('device_setting',per_device = True)
def _set_device_setting(self,value,device,sim): def _set_device_setting(self,value,device,sim,remove):
device.setting = value device.setting = value
return device.setting return device.setting

View file

@ -506,7 +506,7 @@ class Plugin(object):
else: else:
new_value = self._check_and_save_value(instance, command, device, new_value) new_value = self._check_and_save_value(instance, command, device, new_value)
if new_value is not None: if new_value is not None:
command["set"](new_value, device, sim = False) command["set"](new_value, device, sim = False, remove = False)
def _execute_non_device_command(self, instance, command, new_value): def _execute_non_device_command(self, instance, command, new_value):
if command["custom"] is not None: if command["custom"] is not None:
@ -514,7 +514,7 @@ class Plugin(object):
else: else:
new_value = self._check_and_save_value(instance, command, None, new_value) new_value = self._check_and_save_value(instance, command, None, new_value)
if new_value is not None: if new_value is not None:
command["set"](new_value, sim = False) command["set"](new_value, sim = False, remove = False)
def _norm_value(self, value): def _norm_value(self, value):
v = self._cmd.unquote(str(value)) v = self._cmd.unquote(str(value))
@ -576,7 +576,7 @@ class Plugin(object):
new_value = self._process_assignment_modifiers(new_value, current_value) new_value = self._process_assignment_modifiers(new_value, current_value)
if new_value is None: if new_value is None:
return None return None
new_value = command["set"](new_value, device, True) new_value = command["set"](new_value, device, True, False)
return self._verify_value(command["name"], new_value, current_value, ignore_missing, device) return self._verify_value(command["name"], new_value, current_value, ignore_missing, device)
def _verify_non_device_command(self, instance, command, new_value, ignore_missing): def _verify_non_device_command(self, instance, command, new_value, ignore_missing):
@ -586,7 +586,7 @@ class Plugin(object):
new_value = self._process_assignment_modifiers(new_value, current_value) new_value = self._process_assignment_modifiers(new_value, current_value)
if new_value is None: if new_value is None:
return None return None
new_value = command["set"](new_value, True) new_value = command["set"](new_value, True, False)
return self._verify_value(command["name"], new_value, current_value, ignore_missing) return self._verify_value(command["name"], new_value, current_value, ignore_missing)
def _cleanup_all_non_device_commands(self, instance): def _cleanup_all_non_device_commands(self, instance):
@ -594,19 +594,19 @@ class Plugin(object):
if (instance.options.get(command["name"], None) is not None) or (command["name"] in self._options_used_by_dynamic): if (instance.options.get(command["name"], None) is not None) or (command["name"] in self._options_used_by_dynamic):
self._cleanup_non_device_command(instance, command) self._cleanup_non_device_command(instance, command)
def _cleanup_all_device_commands(self, instance, devices): def _cleanup_all_device_commands(self, instance, devices, remove = False):
for command in reversed([command for command in list(self._commands.values()) if command["per_device"]]): for command in reversed([command for command in list(self._commands.values()) if command["per_device"]]):
if (instance.options.get(command["name"], None) is not None) or (command["name"] in self._options_used_by_dynamic): if (instance.options.get(command["name"], None) is not None) or (command["name"] in self._options_used_by_dynamic):
for device in devices: for device in devices:
self._cleanup_device_command(instance, command, device) self._cleanup_device_command(instance, command, device, remove)
def _cleanup_device_command(self, instance, command, device): def _cleanup_device_command(self, instance, command, device, remove = False):
if command["custom"] is not None: if command["custom"] is not None:
command["custom"](False, None, device, False, False) command["custom"](False, None, device, False, False)
else: else:
old_value = self._storage_get(instance, command, device) old_value = self._storage_get(instance, command, device)
if old_value is not None: if old_value is not None:
command["set"](old_value, device, sim = False) command["set"](old_value, device, sim = False, remove = remove)
self._storage_unset(instance, command, device) self._storage_unset(instance, command, device)
def _cleanup_non_device_command(self, instance, command): def _cleanup_non_device_command(self, instance, command):
@ -615,5 +615,5 @@ class Plugin(object):
else: else:
old_value = self._storage_get(instance, command) old_value = self._storage_get(instance, command)
if old_value is not None: if old_value is not None:
command["set"](old_value, sim = False) command["set"](old_value, sim = False, remove = False)
self._storage_unset(instance, command) self._storage_unset(instance, command)

View file

@ -109,4 +109,4 @@ class Plugin(base.Plugin):
def _removed_device_unapply_tuning(self, 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.has_dynamic_tuning and self._global_cfg.get(consts.CFG_DYNAMIC_TUNING, consts.CFG_DEF_DYNAMIC_TUNING):
self._instance_unapply_dynamic(instance, device_name) self._instance_unapply_dynamic(instance, device_name)
self._cleanup_all_device_commands(instance, [device_name]) self._cleanup_all_device_commands(instance, [device_name], remove = True)

View file

@ -4,6 +4,7 @@ import tuned.logs
from tuned.utils.commands import commands from tuned.utils.commands import commands
import os import os
import errno
import struct import struct
import glob import glob
@ -73,7 +74,7 @@ class AudioPlugin(hotplug.Plugin):
return "/sys/module/%s/parameters/power_save_controller" % device return "/sys/module/%s/parameters/power_save_controller" % device
@command_set("timeout", per_device = True) @command_set("timeout", per_device = True)
def _set_timeout(self, value, device, sim): def _set_timeout(self, value, device, sim, remove):
try: try:
timeout = int(value) timeout = int(value)
except ValueError: except ValueError:
@ -82,7 +83,8 @@ class AudioPlugin(hotplug.Plugin):
if timeout >= 0: if timeout >= 0:
sys_file = self._timeout_path(device) sys_file = self._timeout_path(device)
if not sim: if not sim:
cmd.write_to_file(sys_file, "%d" % timeout) cmd.write_to_file(sys_file, "%d" % timeout, \
no_error = [errno.ENOENT] if remove else False)
return timeout return timeout
else: else:
return None return None
@ -96,12 +98,13 @@ class AudioPlugin(hotplug.Plugin):
return None return None
@command_set("reset_controller", per_device = True) @command_set("reset_controller", per_device = True)
def _set_reset_controller(self, value, device, sim): def _set_reset_controller(self, value, device, sim, remove):
v = cmd.get_bool(value) v = cmd.get_bool(value)
sys_file = self._reset_controller_path(device) sys_file = self._reset_controller_path(device)
if os.path.exists(sys_file): if os.path.exists(sys_file):
if not sim: if not sim:
cmd.write_to_file(sys_file, v) cmd.write_to_file(sys_file, v, \
no_error = [errno.ENOENT] if remove else False)
return v return v
return None return None

View file

@ -5,6 +5,7 @@ from tuned.utils.commands import commands
import tuned.consts as consts import tuned.consts as consts
import os import os
import errno
import struct import struct
import errno import errno
import platform import platform
@ -500,7 +501,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_available_governors" % device).strip().split() return self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_available_governors" % device).strip().split()
@command_set("governor", per_device=True) @command_set("governor", per_device=True)
def _set_governor(self, governors, device, sim): def _set_governor(self, governors, device, sim, remove):
if not self._check_cpu_can_change_governor(device): if not self._check_cpu_can_change_governor(device):
return None return None
governors = str(governors) governors = str(governors)
@ -517,7 +518,7 @@ class CPULatencyPlugin(hotplug.Plugin):
log.info("setting governor '%s' on cpu '%s'" log.info("setting governor '%s' on cpu '%s'"
% (governor, device)) % (governor, device))
self._cmd.write_to_file("/sys/devices/system/cpu/%s/cpufreq/scaling_governor" self._cmd.write_to_file("/sys/devices/system/cpu/%s/cpufreq/scaling_governor"
% device, governor) % device, governor, no_error = [errno.ENOENT] if remove else False)
break break
elif not sim: elif not sim:
log.debug("Ignoring governor '%s' on cpu '%s', it is not supported" log.debug("Ignoring governor '%s' on cpu '%s', it is not supported"
@ -546,7 +547,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return "/sys/devices/system/cpu/cpufreq/%s/sampling_down_factor" % governor return "/sys/devices/system/cpu/cpufreq/%s/sampling_down_factor" % governor
@command_set("sampling_down_factor", per_device = True, priority = 10) @command_set("sampling_down_factor", per_device = True, priority = 10)
def _set_sampling_down_factor(self, sampling_down_factor, device, sim): def _set_sampling_down_factor(self, sampling_down_factor, device, sim, remove):
val = None val = None
# hack to clear governors map when the profile starts unloading # hack to clear governors map when the profile starts unloading
@ -569,7 +570,7 @@ class CPULatencyPlugin(hotplug.Plugin):
val = str(sampling_down_factor) val = str(sampling_down_factor)
if not sim: if not sim:
log.info("setting sampling_down_factor to '%s' for governor '%s'" % (val, governor)) log.info("setting sampling_down_factor to '%s' for governor '%s'" % (val, governor))
self._cmd.write_to_file(path, val) self._cmd.write_to_file(path, val, no_error = [errno.ENOENT] if remove else False)
return val return val
@command_get("sampling_down_factor") @command_get("sampling_down_factor")
@ -598,7 +599,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return "/sys/devices/system/cpu/cpu%s/power/energy_perf_bias" % cpu_id return "/sys/devices/system/cpu/cpu%s/power/energy_perf_bias" % cpu_id
@command_set("energy_perf_bias", per_device=True) @command_set("energy_perf_bias", per_device=True)
def _set_energy_perf_bias(self, energy_perf_bias, device, sim): def _set_energy_perf_bias(self, energy_perf_bias, device, sim, remove):
if not self._is_cpu_online(device): if not self._is_cpu_online(device):
log.debug("%s is not online, skipping" % device) log.debug("%s is not online, skipping" % device)
return None return None
@ -613,10 +614,11 @@ class CPULatencyPlugin(hotplug.Plugin):
if not sim: if not sim:
for val in vals: for val in vals:
val = val.strip() val = val.strip()
if self._cmd.write_to_file(energy_perf_bias_path, val): if self._cmd.write_to_file(energy_perf_bias_path, val, \
log.info("energy_perf_bias successfully set to '%s' on cpu '%s'" no_error = [errno.ENOENT] if remove else False):
% (val, device)) log.info("energy_perf_bias successfully set to '%s' on cpu '%s'"
break % (val, device))
break
else: else:
log.error("Failed to set energy_perf_bias on cpu '%s'. Is the value in the profile correct?" log.error("Failed to set energy_perf_bias on cpu '%s'. Is the value in the profile correct?"
% device) % device)
@ -711,7 +713,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return self._has_pm_qos_resume_latency_us return self._has_pm_qos_resume_latency_us
@command_set("pm_qos_resume_latency_us", per_device=True) @command_set("pm_qos_resume_latency_us", per_device=True)
def _set_pm_qos_resume_latency_us(self, pm_qos_resume_latency_us, device, sim): def _set_pm_qos_resume_latency_us(self, pm_qos_resume_latency_us, device, sim, remove):
if not self._is_cpu_online(device): if not self._is_cpu_online(device):
log.debug("%s is not online, skipping" % device) log.debug("%s is not online, skipping" % device)
return None return None
@ -729,7 +731,8 @@ class CPULatencyPlugin(hotplug.Plugin):
if not self._check_pm_qos_resume_latency_us(device): if not self._check_pm_qos_resume_latency_us(device):
return None return None
if not sim: if not sim:
self._cmd.write_to_file(self._pm_qos_resume_latency_us_path(device), latency) self._cmd.write_to_file(self._pm_qos_resume_latency_us_path(device), latency, \
no_error = [errno.ENOENT] if remove else False)
return latency return latency
@command_get("pm_qos_resume_latency_us") @command_get("pm_qos_resume_latency_us")
@ -742,7 +745,7 @@ class CPULatencyPlugin(hotplug.Plugin):
return self._cmd.read_file(self._pm_qos_resume_latency_us_path(device), no_error=ignore_missing).strip() return self._cmd.read_file(self._pm_qos_resume_latency_us_path(device), no_error=ignore_missing).strip()
@command_set("energy_performance_preference", per_device=True) @command_set("energy_performance_preference", per_device=True)
def _set_energy_performance_preference(self, energy_performance_preference, device, sim): def _set_energy_performance_preference(self, energy_performance_preference, device, sim, remove):
if not self._is_cpu_online(device): if not self._is_cpu_online(device):
log.debug("%s is not online, skipping" % device) log.debug("%s is not online, skipping" % device)
return None return None
@ -753,7 +756,8 @@ class CPULatencyPlugin(hotplug.Plugin):
avail_vals = set(self._cmd.read_file(self._pstate_preference_path(cpu_id, True)).split()) avail_vals = set(self._cmd.read_file(self._pstate_preference_path(cpu_id, True)).split())
for val in vals: for val in vals:
if val in avail_vals: if val in avail_vals:
self._cmd.write_to_file(self._pstate_preference_path(cpu_id), val) self._cmd.write_to_file(self._pstate_preference_path(cpu_id), val, \
no_error = [errno.ENOENT] if remove else False)
log.info("Setting energy_performance_preference value '%s' for cpu '%s'" % (val, device)) log.info("Setting energy_performance_preference value '%s' for cpu '%s'" % (val, device))
break break
else: else:

View file

@ -335,10 +335,11 @@ class DiskPlugin(hotplug.Plugin):
return self._sysfs_path(device, "queue/scheduler") return self._sysfs_path(device, "queue/scheduler")
@command_set("elevator", per_device=True) @command_set("elevator", per_device=True)
def _set_elevator(self, value, device, sim): def _set_elevator(self, value, device, sim, remove):
sys_file = self._elevator_file(device) sys_file = self._elevator_file(device)
if not sim: if not sim:
self._cmd.write_to_file(sys_file, value) self._cmd.write_to_file(sys_file, value, \
no_error = [errno.ENOENT] if remove else False)
return value return value
@command_get("elevator") @command_get("elevator")
@ -349,7 +350,7 @@ class DiskPlugin(hotplug.Plugin):
return self._cmd.get_active_option(self._cmd.read_file(sys_file, no_error=ignore_missing)) return self._cmd.get_active_option(self._cmd.read_file(sys_file, no_error=ignore_missing))
@command_set("apm", per_device=True) @command_set("apm", per_device=True)
def _set_apm(self, value, device, sim): def _set_apm(self, value, device, sim, remove):
if device not in self._hdparm_apm_devices: if device not in self._hdparm_apm_devices:
if not sim: if not sim:
log.info("apm option is not supported for device '%s'" % device) log.info("apm option is not supported for device '%s'" % device)
@ -389,7 +390,7 @@ class DiskPlugin(hotplug.Plugin):
return value return value
@command_set("spindown", per_device=True) @command_set("spindown", per_device=True)
def _set_spindown(self, value, device, sim): def _set_spindown(self, value, device, sim, remove):
if device not in self._hdparm_apm_devices: if device not in self._hdparm_apm_devices:
if not sim: if not sim:
log.info("spindown option is not supported for device '%s'" % device) log.info("spindown option is not supported for device '%s'" % device)
@ -428,14 +429,15 @@ class DiskPlugin(hotplug.Plugin):
return v return v
@command_set("readahead", per_device=True) @command_set("readahead", per_device=True)
def _set_readahead(self, value, device, sim): def _set_readahead(self, value, device, sim, remove):
sys_file = self._readahead_file(device) sys_file = self._readahead_file(device)
val = self._parse_ra(value) val = self._parse_ra(value)
if val is None: if val is None:
log.error("Invalid readahead value '%s' for device '%s'" % (value, device)) log.error("Invalid readahead value '%s' for device '%s'" % (value, device))
else: else:
if not sim: if not sim:
self._cmd.write_to_file(sys_file, "%d" % val) self._cmd.write_to_file(sys_file, "%d" % val, \
no_error = [errno.ENOENT] if remove else False)
return val return val
@command_get("readahead") @command_get("readahead")
@ -471,10 +473,11 @@ class DiskPlugin(hotplug.Plugin):
return self._sysfs_path(device, "queue/iosched/quantum") return self._sysfs_path(device, "queue/iosched/quantum")
@command_set("scheduler_quantum", per_device=True) @command_set("scheduler_quantum", per_device=True)
def _set_scheduler_quantum(self, value, device, sim): def _set_scheduler_quantum(self, value, device, sim, remove):
sys_file = self._scheduler_quantum_file(device) sys_file = self._scheduler_quantum_file(device)
if not sim: if not sim:
self._cmd.write_to_file(sys_file, "%d" % int(value)) self._cmd.write_to_file(sys_file, "%d" % int(value), \
no_error = [errno.ENOENT] if remove else False)
return value return value
@command_get("scheduler_quantum") @command_get("scheduler_quantum")

View file

@ -380,7 +380,7 @@ class NetTuningPlugin(hotplug.Plugin):
return "/sys/module/nf_conntrack/parameters/hashsize" return "/sys/module/nf_conntrack/parameters/hashsize"
@command_set("wake_on_lan", per_device=True) @command_set("wake_on_lan", per_device=True)
def _set_wake_on_lan(self, value, device, sim): def _set_wake_on_lan(self, value, device, sim, remove):
if value is None: if value is None:
return None return None
@ -406,14 +406,15 @@ class NetTuningPlugin(hotplug.Plugin):
return value return value
@command_set("nf_conntrack_hashsize") @command_set("nf_conntrack_hashsize")
def _set_nf_conntrack_hashsize(self, value, sim): def _set_nf_conntrack_hashsize(self, value, sim, remove):
if value is None: if value is None:
return None return None
hashsize = int(value) hashsize = int(value)
if hashsize >= 0: if hashsize >= 0:
if not sim: if not sim:
self._cmd.write_to_file(self._nf_conntrack_hashsize_path(), hashsize) self._cmd.write_to_file(self._nf_conntrack_hashsize_path(), hashsize, \
no_error = [errno.ENOENT] if remove else False)
return hashsize return hashsize
else: else:
return None return None
@ -447,7 +448,7 @@ class NetTuningPlugin(hotplug.Plugin):
return self._call_ip_link(args) return self._call_ip_link(args)
@command_set("txqueuelen", per_device=True) @command_set("txqueuelen", per_device=True)
def _set_txqueuelen(self, value, device, sim): def _set_txqueuelen(self, value, device, sim, remove):
if value is None: if value is None:
return None return None
try: try:
@ -487,7 +488,7 @@ class NetTuningPlugin(hotplug.Plugin):
return res.group(1) return res.group(1)
@command_set("mtu", per_device=True) @command_set("mtu", per_device=True)
def _set_mtu(self, value, device, sim): def _set_mtu(self, value, device, sim, remove):
if value is None: if value is None:
return None return None
try: try:

View file

@ -1414,12 +1414,13 @@ class SchedulerPlugin(base.Plugin):
self._secure_boot_hint = False self._secure_boot_hint = False
return data return data
def _set_sched_knob(self, prefix, namespace, knob, value, sim): def _set_sched_knob(self, prefix, namespace, knob, value, sim, remove = False):
if value is None: if value is None:
return None return None
if not sim: if not sim:
if not self._cmd.write_to_file(self._get_sched_knob_path(prefix, namespace, knob), value): if not self._cmd.write_to_file(self._get_sched_knob_path(prefix, namespace, knob), value, \
log.error("Error writing value '%s' to '%s'" % (value, knob)) no_error = [errno.ENOENT] if remove else False):
log.error("Error writing value '%s' to '%s'" % (value, knob))
return value return value
@command_get("sched_min_granularity_ns") @command_get("sched_min_granularity_ns")
@ -1427,77 +1428,77 @@ class SchedulerPlugin(base.Plugin):
return self._get_sched_knob("", "sched", "min_granularity_ns") return self._get_sched_knob("", "sched", "min_granularity_ns")
@command_set("sched_min_granularity_ns") @command_set("sched_min_granularity_ns")
def _set_sched_min_granularity_ns(self, value, sim): def _set_sched_min_granularity_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "min_granularity_ns", value, sim) return self._set_sched_knob("", "sched", "min_granularity_ns", value, sim, remove)
@command_get("sched_latency_ns") @command_get("sched_latency_ns")
def _get_sched_latency_ns(self): def _get_sched_latency_ns(self):
return self._get_sched_knob("", "sched", "latency_ns") return self._get_sched_knob("", "sched", "latency_ns")
@command_set("sched_latency_ns") @command_set("sched_latency_ns")
def _set_sched_latency_ns(self, value, sim): def _set_sched_latency_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "latency_ns", value, sim) return self._set_sched_knob("", "sched", "latency_ns", value, sim, remove)
@command_get("sched_wakeup_granularity_ns") @command_get("sched_wakeup_granularity_ns")
def _get_sched_wakeup_granularity_ns(self): def _get_sched_wakeup_granularity_ns(self):
return self._get_sched_knob("", "sched", "wakeup_granularity_ns") return self._get_sched_knob("", "sched", "wakeup_granularity_ns")
@command_set("sched_wakeup_granularity_ns") @command_set("sched_wakeup_granularity_ns")
def _set_sched_wakeup_granularity_ns(self, value, sim): def _set_sched_wakeup_granularity_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "wakeup_granularity_ns", value, sim) return self._set_sched_knob("", "sched", "wakeup_granularity_ns", value, sim, remove)
@command_get("sched_tunable_scaling") @command_get("sched_tunable_scaling")
def _get_sched_tunable_scaling(self): def _get_sched_tunable_scaling(self):
return self._get_sched_knob("", "sched", "tunable_scaling") return self._get_sched_knob("", "sched", "tunable_scaling")
@command_set("sched_tunable_scaling") @command_set("sched_tunable_scaling")
def _set_sched_tunable_scaling(self, value, sim): def _set_sched_tunable_scaling(self, value, sim, remove):
return self._set_sched_knob("", "sched", "tunable_scaling", value, sim) return self._set_sched_knob("", "sched", "tunable_scaling", value, sim, remove)
@command_get("sched_migration_cost_ns") @command_get("sched_migration_cost_ns")
def _get_sched_migration_cost_ns(self): def _get_sched_migration_cost_ns(self):
return self._get_sched_knob("", "sched", "migration_cost_ns") return self._get_sched_knob("", "sched", "migration_cost_ns")
@command_set("sched_migration_cost_ns") @command_set("sched_migration_cost_ns")
def _set_sched_migration_cost_ns(self, value, sim): def _set_sched_migration_cost_ns(self, value, sim, remove):
return self._set_sched_knob("", "sched", "migration_cost_ns", value, sim) return self._set_sched_knob("", "sched", "migration_cost_ns", value, sim, remove)
@command_get("sched_nr_migrate") @command_get("sched_nr_migrate")
def _get_sched_nr_migrate(self): def _get_sched_nr_migrate(self):
return self._get_sched_knob("", "sched", "nr_migrate") return self._get_sched_knob("", "sched", "nr_migrate")
@command_set("sched_nr_migrate") @command_set("sched_nr_migrate")
def _set_sched_nr_migrate(self, value, sim): def _set_sched_nr_migrate(self, value, sim, remove):
return self._set_sched_knob("", "sched", "nr_migrate", value, sim) return self._set_sched_knob("", "sched", "nr_migrate", value, sim, remove)
@command_get("numa_balancing_scan_delay_ms") @command_get("numa_balancing_scan_delay_ms")
def _get_numa_balancing_scan_delay_ms(self): def _get_numa_balancing_scan_delay_ms(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_delay_ms") return self._get_sched_knob("sched", "numa_balancing", "scan_delay_ms")
@command_set("numa_balancing_scan_delay_ms") @command_set("numa_balancing_scan_delay_ms")
def _set_numa_balancing_scan_delay_ms(self, value, sim): def _set_numa_balancing_scan_delay_ms(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_delay_ms", value, sim) return self._set_sched_knob("sched", "numa_balancing", "scan_delay_ms", value, sim, remove)
@command_get("numa_balancing_scan_period_min_ms") @command_get("numa_balancing_scan_period_min_ms")
def _get_numa_balancing_scan_period_min_ms(self): def _get_numa_balancing_scan_period_min_ms(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_period_min_ms") return self._get_sched_knob("sched", "numa_balancing", "scan_period_min_ms")
@command_set("numa_balancing_scan_period_min_ms") @command_set("numa_balancing_scan_period_min_ms")
def _set_numa_balancing_scan_period_min_ms(self, value, sim): def _set_numa_balancing_scan_period_min_ms(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_period_min_ms", value, sim) return self._set_sched_knob("sched", "numa_balancing", "scan_period_min_ms", value, sim, remove)
@command_get("numa_balancing_scan_period_max_ms") @command_get("numa_balancing_scan_period_max_ms")
def _get_numa_balancing_scan_period_max_ms(self): def _get_numa_balancing_scan_period_max_ms(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_period_max_ms") return self._get_sched_knob("sched", "numa_balancing", "scan_period_max_ms")
@command_set("numa_balancing_scan_period_max_ms") @command_set("numa_balancing_scan_period_max_ms")
def _set_numa_balancing_scan_period_max_ms(self, value, sim): def _set_numa_balancing_scan_period_max_ms(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_period_max_ms", value, sim) return self._set_sched_knob("sched", "numa_balancing", "scan_period_max_ms", value, sim, remove)
@command_get("numa_balancing_scan_size_mb") @command_get("numa_balancing_scan_size_mb")
def _get_numa_balancing_scan_size_mb(self): def _get_numa_balancing_scan_size_mb(self):
return self._get_sched_knob("sched", "numa_balancing", "scan_size_mb") return self._get_sched_knob("sched", "numa_balancing", "scan_size_mb")
@command_set("numa_balancing_scan_size_mb") @command_set("numa_balancing_scan_size_mb")
def _set_numa_balancing_scan_size_mb(self, value, sim): def _set_numa_balancing_scan_size_mb(self, value, sim, remove):
return self._set_sched_knob("sched", "numa_balancing", "scan_size_mb", value, sim) return self._set_sched_knob("sched", "numa_balancing", "scan_size_mb", value, sim, remove)

View file

@ -86,13 +86,14 @@ class SCSIHostPlugin(hotplug.Plugin):
return os.path.join("/sys/class/scsi_host/", str(device), "link_power_management_policy") return os.path.join("/sys/class/scsi_host/", str(device), "link_power_management_policy")
@command_set("alpm", per_device = True) @command_set("alpm", per_device = True)
def _set_alpm(self, policy, device, sim): def _set_alpm(self, policy, device, sim, remove):
if policy is None: if policy is None:
return None return None
policy_file = self._get_alpm_policy_file(device) policy_file = self._get_alpm_policy_file(device)
if not sim: if not sim:
if os.path.exists(policy_file): if os.path.exists(policy_file):
self._cmd.write_to_file(policy_file, policy) self._cmd.write_to_file(policy_file, policy, \
no_error = [errno.ENOENT] if remove else False)
else: else:
log.info("ALPM control file ('%s') not found, skipping ALPM setting for '%s'" % (policy_file, str(device))) log.info("ALPM control file ('%s') not found, skipping ALPM setting for '%s'" % (policy_file, str(device)))
return None return None

View file

@ -1,4 +1,5 @@
import os import os
import errno
from . import base from . import base
from .decorators import * from .decorators import *
import tuned.logs import tuned.logs
@ -63,13 +64,14 @@ class SelinuxPlugin(base.Plugin):
pass pass
@command_set("avc_cache_threshold") @command_set("avc_cache_threshold")
def _set_avc_cache_threshold(self, value, sim): def _set_avc_cache_threshold(self, value, sim, remove):
if value is None: if value is None:
return None return None
threshold = int(value) threshold = int(value)
if threshold >= 0: if threshold >= 0:
if not sim: if not sim:
self._cmd.write_to_file(self._cache_threshold_path, threshold) self._cmd.write_to_file(self._cache_threshold_path, threshold, \
no_error = [errno.ENOENT] if remove else False)
return threshold return threshold
else: else:
return None return None

View file

@ -3,6 +3,7 @@ from .decorators import *
import tuned.logs import tuned.logs
from tuned.utils.commands import commands from tuned.utils.commands import commands
import glob import glob
import errno
log = tuned.logs.get() log = tuned.logs.get()
@ -57,7 +58,7 @@ class USBPlugin(base.Plugin):
return "/sys/bus/usb/devices/%s/power/autosuspend" % device return "/sys/bus/usb/devices/%s/power/autosuspend" % device
@command_set("autosuspend", per_device=True) @command_set("autosuspend", per_device=True)
def _set_autosuspend(self, value, device, sim): def _set_autosuspend(self, value, device, sim, remove):
enable = self._option_bool(value) enable = self._option_bool(value)
if enable is None: if enable is None:
return None return None
@ -65,7 +66,8 @@ class USBPlugin(base.Plugin):
val = "1" if enable else "0" val = "1" if enable else "0"
if not sim: if not sim:
sys_file = self._autosuspend_sysfile(device) sys_file = self._autosuspend_sysfile(device)
self._cmd.write_to_file(sys_file, val) self._cmd.write_to_file(sys_file, val, \
no_error = [errno.ENOENT] if remove else False)
return val return val
@command_get("autosuspend") @command_get("autosuspend")

View file

@ -3,6 +3,7 @@ from .decorators import *
import tuned.logs import tuned.logs
from tuned.utils.commands import commands from tuned.utils.commands import commands
import os import os
import errno
import re import re
log = tuned.logs.get() log = tuned.logs.get()
@ -76,7 +77,7 @@ class VideoPlugin(base.Plugin):
} }
@command_set("radeon_powersave", per_device=True) @command_set("radeon_powersave", per_device=True)
def _set_radeon_powersave(self, value, device, sim): def _set_radeon_powersave(self, value, device, sim, remove):
sys_files = self._radeon_powersave_files(device) sys_files = self._radeon_powersave_files(device)
va = str(re.sub(r"(\s*:\s*)|(\s+)|(\s*;\s*)|(\s*,\s*)", " ", value)).split() va = str(re.sub(r"(\s*:\s*)|(\s+)|(\s*;\s*)|(\s*,\s*)", " ", value)).split()
if not os.path.exists(sys_files["method"]): if not os.path.exists(sys_files["method"]):
@ -86,20 +87,25 @@ class VideoPlugin(base.Plugin):
for v in va: for v in va:
if v in ["default", "auto", "low", "mid", "high"]: if v in ["default", "auto", "low", "mid", "high"]:
if not sim: if not sim:
if (self._cmd.write_to_file(sys_files["method"], "profile") and if (self._cmd.write_to_file(sys_files["method"], "profile", \
self._cmd.write_to_file(sys_files["profile"], v)): no_error = [errno.ENOENT] if remove else False) and
return v self._cmd.write_to_file(sys_files["profile"], v, \
no_error = [errno.ENOENT] if remove else False)):
return v
elif v == "dynpm": elif v == "dynpm":
if not sim: if not sim:
if (self._cmd.write_to_file(sys_files["method"], "dynpm")): if (self._cmd.write_to_file(sys_files["method"], "dynpm", \
return "dynpm" no_error = [errno.ENOENT] if remove else False)):
return "dynpm"
# new DPM profiles, recommended to use if supported # new DPM profiles, recommended to use if supported
elif v in ["dpm-battery", "dpm-balanced", "dpm-performance"]: elif v in ["dpm-battery", "dpm-balanced", "dpm-performance"]:
if not sim: if not sim:
state = v[len("dpm-"):] state = v[len("dpm-"):]
if (self._cmd.write_to_file(sys_files["method"], "dpm") and if (self._cmd.write_to_file(sys_files["method"], "dpm", \
self._cmd.write_to_file(sys_files["dpm_state"], state)): no_error = [errno.ENOENT] if remove else False) and
return v self._cmd.write_to_file(sys_files["dpm_state"], state, \
no_error = [errno.ENOENT] if remove else False)):
return v
else: else:
if not sim: if not sim:
log.warn("Invalid option for radeon_powersave.") log.warn("Invalid option for radeon_powersave.")

View file

@ -3,6 +3,7 @@ from .decorators import *
import tuned.logs import tuned.logs
import os import os
import errno
import struct import struct
import glob import glob
from tuned.utils.commands import commands from tuned.utils.commands import commands
@ -57,7 +58,7 @@ class VMPlugin(base.Plugin):
return path return path
@command_set("transparent_hugepages") @command_set("transparent_hugepages")
def _set_transparent_hugepages(self, value, sim): def _set_transparent_hugepages(self, value, sim, remove):
if value not in ["always", "never", "madvise"]: if value not in ["always", "never", "madvise"]:
if not sim: if not sim:
log.warn("Incorrect 'transparent_hugepages' value '%s'." % str(value)) log.warn("Incorrect 'transparent_hugepages' value '%s'." % str(value))
@ -72,7 +73,8 @@ class VMPlugin(base.Plugin):
sys_file = os.path.join(self._thp_path(), "enabled") sys_file = os.path.join(self._thp_path(), "enabled")
if os.path.exists(sys_file): if os.path.exists(sys_file):
if not sim: if not sim:
cmd.write_to_file(sys_file, value) cmd.write_to_file(sys_file, value, \
no_error = [errno.ENOENT] if remove else False)
return value return value
else: else:
if not sim: if not sim:
@ -81,8 +83,8 @@ class VMPlugin(base.Plugin):
# just an alias to transparent_hugepages # just an alias to transparent_hugepages
@command_set("transparent_hugepage") @command_set("transparent_hugepage")
def _set_transparent_hugepage(self, value, sim): def _set_transparent_hugepage(self, value, sim, remove):
self._set_transparent_hugepages(value, sim) self._set_transparent_hugepages(value, sim, remove)
@command_get("transparent_hugepages") @command_get("transparent_hugepages")
def _get_transparent_hugepages(self): def _get_transparent_hugepages(self):
@ -98,11 +100,12 @@ class VMPlugin(base.Plugin):
return self._get_transparent_hugepages() return self._get_transparent_hugepages()
@command_set("transparent_hugepage.defrag") @command_set("transparent_hugepage.defrag")
def _set_transparent_hugepage_defrag(self, value, sim): def _set_transparent_hugepage_defrag(self, value, sim, remove):
sys_file = os.path.join(self._thp_path(), "defrag") sys_file = os.path.join(self._thp_path(), "defrag")
if os.path.exists(sys_file): if os.path.exists(sys_file):
if not sim: if not sim:
cmd.write_to_file(sys_file, value) cmd.write_to_file(sys_file, value, \
no_error = [errno.ENOENT] if remove else False)
return value return value
else: else:
if not sim: if not sim:

View file

@ -91,6 +91,17 @@ class commands:
return None return None
def write_to_file(self, f, data, makedir = False, no_error = False): def write_to_file(self, f, data, makedir = False, no_error = False):
"""Write data to a file.
Parameters:
f -- filename where to write
data -- data to write
makedir -- if True and the path doesn't exist, it will be created
no_error -- if True errors are silenced, it can be also list of ignored errnos
Return:
bool -- True on success
"""
self._debug("Writing to file: '%s' < '%s'" % (f, data)) self._debug("Writing to file: '%s' < '%s'" % (f, data))
if makedir: if makedir:
d = os.path.dirname(f) d = os.path.dirname(f)
@ -103,10 +114,11 @@ class commands:
fd.write(str(data)) fd.write(str(data))
fd.close() fd.close()
rc = True rc = True
except (OSError,IOError) as e: except (OSError, IOError) as e:
rc = False rc = False
if not no_error: if isinstance(no_error, bool) and not no_error or \
self._error("Writing to file '%s' error: '%s'" % (f, e)) isinstance(no_error, list) and e.errno not in no_error:
self._error("Writing to file '%s' error: '%s'" % (f, e))
return rc return rc
def read_file(self, f, err_ret = "", no_error = False): def read_file(self, f, err_ret = "", no_error = False):