diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..37b5c38 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/tuned-2.3.0.tar.bz2 diff --git a/.tuned.metadata b/.tuned.metadata new file mode 100644 index 0000000..1328a39 --- /dev/null +++ b/.tuned.metadata @@ -0,0 +1 @@ +e0bcdb54215e38738f9a0e564d3309476b8545bd SOURCES/tuned-2.3.0.tar.bz2 diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/tuned-2.3.0-assignment-modifiers.patch b/SOURCES/tuned-2.3.0-assignment-modifiers.patch new file mode 100644 index 0000000..62d3262 --- /dev/null +++ b/SOURCES/tuned-2.3.0-assignment-modifiers.patch @@ -0,0 +1,115 @@ +From 1d1c3a389c393afa1e88d5629f5dff85824fc92b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= +Date: Wed, 7 May 2014 17:02:59 +0200 +Subject: tuned: Added support for >, < assignment modifiers in tuned.conf +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These modifiers can specify when to assign new value considering +the old value. + +E.g.: +readahead=>4096 + +means assign readahead 4096 only if the current value of readahaed +is lower than 4096 (i.e. the readahaed will be at least 4096). + +Similarly for the < operator, it will assign the value only +if the current value is higher. + +The modifiers are part of the value, not part of the equality +operator, thus the following is correct: +readahead= >4096 + +But the following isn't correct, but will probably also work +due to the nature how the value is parsed: +readahead=> 4096 + +Signed-off-by: Jaroslav Škarvada + +diff --git a/profiles/throughput-performance/tuned.conf b/profiles/throughput-performance/tuned.conf +index dae02dc..42473a9 100644 +--- a/profiles/throughput-performance/tuned.conf ++++ b/profiles/throughput-performance/tuned.conf +@@ -11,7 +11,7 @@ min_perf_pct=100 + transparent_hugepages=always + + [disk] +-readahead=4096 ++readahead=>4096 + + [sysctl] + # ktune sysctl settings for rhel6 servers, maximizing i/o throughput +diff --git a/tuned/plugins/base.py b/tuned/plugins/base.py +index bad487f..f0faf38 100644 +--- a/tuned/plugins/base.py ++++ b/tuned/plugins/base.py +@@ -212,7 +212,7 @@ class Plugin(object): + + def _instance_apply_dynamic(self, instance, device): + for option in filter(lambda opt: self._storage_get(instance, self._commands[opt], device) is None, self._options_used_by_dynamic): +- self._save_current_value(instance, self._commands[option], device) ++ self._check_and_save_value(instance, self._commands[option], device) + + self._instance_update_dynamic(instance, device) + +@@ -317,27 +317,50 @@ class Plugin(object): + for device in devices: + self._execute_device_command(instance, command, device, new_value) + +- def _save_current_value(self, instance, command, device = None): ++ def _check_and_save_value(self, instance, command, device = None, new_value = None): + if device is not None: + current_value = command["get"](device) + else: + current_value = command["get"]() ++ if new_value is not None: ++ nws = str(new_value) ++ op = nws[:1] ++ val = nws[1:] ++ try: ++ if op == ">": ++ if int(val) > int(current_value): ++ new_value = val; ++ else: ++ current_value = None ++ new_value = None ++ elif op == "<": ++ if int(val) < int(current_value): ++ new_value = val; ++ else: ++ current_value = None ++ new_value = None ++ except ValueError: ++ log.warn("cannot compare new value '%s' with current value '%s' by operator '%s', using '%s' directly as new value" % (val, current_value, op, new_value)) ++ + if current_value is not None: + self._storage_set(instance, command, current_value, device) ++ return new_value + + def _execute_device_command(self, instance, command, device, new_value): + if command["custom"] is not None: + command["custom"](True, new_value, device) + else: +- self._save_current_value(instance, command, device) +- command["set"](new_value, device) ++ new_value = self._check_and_save_value(instance, command, device, new_value) ++ if new_value is not None: ++ command["set"](new_value, device) + + def _execute_non_device_command(self, instance, command, new_value): + if command["custom"] is not None: + command["custom"](True, new_value) + else: +- self._save_current_value(instance, command) +- command["set"](new_value) ++ new_value = self._check_and_save_value(instance, command, None, new_value) ++ if new_value is not None: ++ command["set"](new_value) + + def _cleanup_all_non_device_commands(self, instance): + for command in filter(lambda command: not command["per_device"], self._commands.values()): +-- +cgit v0.10.1 + diff --git a/SOURCES/tuned-2.3.0-atomic.patch b/SOURCES/tuned-2.3.0-atomic.patch new file mode 100644 index 0000000..940830f --- /dev/null +++ b/SOURCES/tuned-2.3.0-atomic.patch @@ -0,0 +1,190 @@ +diff --git a/man/tuned-adm.8 b/man/tuned-adm.8 +index 7b2b693..01dcd18 100644 +--- a/man/tuned-adm.8 ++++ b/man/tuned-adm.8 +@@ -138,6 +138,18 @@ Profile optimized for virtual hosts based on throughput-performance profile. + It additionally enables more aggresive writeback of dirty pages. + + .TP ++.BI "atomic-guest" ++Profile optimized for virtual Atomic guests. It is based on virtual-guest ++profile. It additionally increases SELinux AVC cache, PID limit and tunes ++netfilter connections tracking. ++ ++.TP ++.BI "atomic-host" ++Profile optimized for Atomic hosts. It is based on throughput-performance ++profile. It additionally increases SELinux AVC cache, PID limit and tunes ++netfilter connections tracking. ++ ++.TP + .BI "sap" + Profile optimized for the best performance of SAP software. It is based on + throughput-performance profile. It additionally tunes sysctl settings +diff --git a/profiles/atomic-guest/tuned.conf b/profiles/atomic-guest/tuned.conf +new file mode 100644 +index 0000000..aff05f2 +--- /dev/null ++++ b/profiles/atomic-guest/tuned.conf +@@ -0,0 +1,16 @@ ++# ++# tuned configuration ++# ++ ++[main] ++include=virtual-guest ++ ++[selinux] ++avc_cache_threshold=65536 ++ ++[net] ++nf_conntrack_hashsize=131072 ++ ++[sysctl] ++kernel.pid_max=131072 ++net.netfilter.nf_conntrack_max=1048576 +diff --git a/profiles/atomic-host/tuned.conf b/profiles/atomic-host/tuned.conf +new file mode 100644 +index 0000000..ad223bd +--- /dev/null ++++ b/profiles/atomic-host/tuned.conf +@@ -0,0 +1,16 @@ ++# ++# tuned configuration ++# ++ ++[main] ++include=throughput-performance ++ ++[selinux] ++avc_cache_threshold=65536 ++ ++[net] ++nf_conntrack_hashsize=131072 ++ ++[sysctl] ++kernel.pid_max=131072 ++net.netfilter.nf_conntrack_max=1048576 +diff --git a/recommend.conf b/recommend.conf +index d01ebdf..45eed36 100644 +--- a/recommend.conf ++++ b/recommend.conf +@@ -7,6 +7,14 @@ + # If 'virt' or 'system' is empty, i.e. 'virt=', it matches only empty string (alias for '^$'). + # If several profiles matched, the first match is taken. + ++[atomic-host] ++virt= ++system=.*atomic.* ++ ++[atomic-guest] ++virt=.+ ++system=.*atomic.* ++ + [throughput-performance] + virt= + system=.*(computenode|server).* +diff --git a/tuned/plugins/plugin_net.py b/tuned/plugins/plugin_net.py +index 57e4265..b9a60b4 100644 +--- a/tuned/plugins/plugin_net.py ++++ b/tuned/plugins/plugin_net.py +@@ -75,6 +75,7 @@ class NetTuningPlugin(base.Plugin): + def _get_config_options(cls): + return { + "wake_on_lan": None, ++ "nf_conntrack_hashsize": None, + } + + def _init_stats_and_idle(self, instance, device): +@@ -121,6 +122,10 @@ class NetTuningPlugin(base.Plugin): + # speed / 7 Mb -> MB + return (int) (0.6 * 1024 * 1024 * speed / 8) + ++ @classmethod ++ def _nf_conntrack_hashsize_path(self): ++ return "/sys/module/nf_conntrack/parameters/hashsize" ++ + @command_set("wake_on_lan", per_device=True) + def _set_wake_on_lan(self, value, device): + if value is None: +@@ -144,3 +149,19 @@ class NetTuningPlugin(base.Plugin): + except IOError: + pass + return value ++ ++ @command_set("nf_conntrack_hashsize") ++ def _set_nf_conntrack_hashsize(self, value): ++ if value is None: ++ return ++ ++ hashsize = int(value) ++ if hashsize >= 0: ++ tuned.utils.commands.write_to_file(self._nf_conntrack_hashsize_path(), hashsize) ++ ++ @command_get("nf_conntrack_hashsize") ++ def _get_nf_conntrack_hashsize(self): ++ value = tuned.utils.commands.read_file(self._nf_conntrack_hashsize_path()) ++ if len(value) > 0: ++ return int(value) ++ return None +diff --git a/tuned/plugins/plugin_selinux.py b/tuned/plugins/plugin_selinux.py +new file mode 100644 +index 0000000..757ecf7 +--- /dev/null ++++ b/tuned/plugins/plugin_selinux.py +@@ -0,0 +1,55 @@ ++import os ++import base ++from decorators import * ++import tuned.logs ++import tuned.utils.commands ++ ++log = tuned.logs.get() ++ ++class SelinuxPlugin(base.Plugin): ++ """ ++ Plugin for tuning SELinux options. ++ """ ++ ++ @classmethod ++ def _get_selinux_path(self): ++ path = "/sys/fs/selinux" ++ if not os.path.exists(path): ++ path = "/selinux" ++ if not os.path.exists(path): ++ path = None ++ return path ++ ++ def __init__(self, *args, **kwargs): ++ self._selinux_path = self._get_selinux_path() ++ if self._selinux_path is None: ++ raise exceptions.NotSupportedPluginException("SELinux is not enabled on your system or incompatible version is used.") ++ self._cache_threshold_path = os.path.join(self._selinux_path, "avc", "cache_threshold") ++ super(self.__class__, self).__init__(*args, **kwargs) ++ ++ def _get_config_options(self): ++ return { ++ "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): ++ if value is None: ++ return ++ threshold = int(value) ++ if threshold >= 0: ++ tuned.utils.commands.write_to_file(self._cache_threshold_path, threshold) ++ ++ @command_get("avc_cache_threshold") ++ def _get_avc_cache_threshold(self): ++ value = tuned.utils.commands.read_file(self._cache_threshold_path) ++ if len(value) > 0: ++ return int(value) ++ return None diff --git a/SOURCES/tuned-2.3.0-cpupower-conflict.patch b/SOURCES/tuned-2.3.0-cpupower-conflict.patch new file mode 100644 index 0000000..44d8c29 --- /dev/null +++ b/SOURCES/tuned-2.3.0-cpupower-conflict.patch @@ -0,0 +1,30 @@ +From 284041dc14f21cd343fed4297cd67ff540d22511 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= +Date: Thu, 6 Mar 2014 17:22:09 +0100 +Subject: [PATCH] systemd: added cpupower.service conflict +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: rhbz#1073392 + +Signed-off-by: Jaroslav Škarvada +--- + tuned.service | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tuned.service b/tuned.service +index e205730..d2d5d83 100644 +--- a/tuned.service ++++ b/tuned.service +@@ -1,6 +1,7 @@ + [Unit] + Description=Dynamic System Tuning Daemon + After=syslog.target ++Conflicts=cpupower.service + + [Service] + Type=dbus +-- +1.8.5.3 + diff --git a/SOURCES/tuned-2.3.0-dirty-ratios.patch b/SOURCES/tuned-2.3.0-dirty-ratios.patch new file mode 100644 index 0000000..da35d92 --- /dev/null +++ b/SOURCES/tuned-2.3.0-dirty-ratios.patch @@ -0,0 +1,37 @@ +From d5aea87c0bad95d5aa51a2ab3ff5d4e741cd856b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= +Date: Tue, 7 Jan 2014 15:38:26 +0100 +Subject: [PATCH] throughput-performance: altered dirty ratios for better + performance +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: rhbz#1043533 + +Signed-off-by: Jaroslav Škarvada +--- + profiles/throughput-performance/tuned.conf | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/profiles/throughput-performance/tuned.conf b/profiles/throughput-performance/tuned.conf +index e6a0551..dae02dc 100644 +--- a/profiles/throughput-performance/tuned.conf ++++ b/profiles/throughput-performance/tuned.conf +@@ -35,11 +35,11 @@ kernel.sched_wakeup_granularity_ns = 15000000 + # + # The generator of dirty data starts writeback at this percentage (system default + # is 20%) +-vm.dirty_ratio = 10 ++vm.dirty_ratio = 40 + + # Start background writeback (via writeback threads) at this percentage (system + # default is 10%) +-vm.dirty_background_ratio = 3 ++vm.dirty_background_ratio = 10 + + # PID allocation wrap value. When the kernel's next PID value + # reaches this value, it wraps back to a minimum PID value. +-- +1.8.4.2 + diff --git a/SOURCES/tuned-2.3.0-fix-race.patch b/SOURCES/tuned-2.3.0-fix-race.patch new file mode 100644 index 0000000..6427fce --- /dev/null +++ b/SOURCES/tuned-2.3.0-fix-race.patch @@ -0,0 +1,20 @@ +diff --git a/tuned/daemon/daemon.py b/tuned/daemon/daemon.py +index 9741cac..804ac0b 100644 +--- a/tuned/daemon/daemon.py ++++ b/tuned/daemon/daemon.py +@@ -65,7 +65,6 @@ class Daemon(object): + self._save_active_profile(self._profile.name) + self._unit_manager.start_tuning() + +- self._terminate.clear() + while not tuned.utils.commands.wait(self._terminate, self._update_interval): + log.debug("updating monitors") + self._unit_manager.update_monitors() +@@ -105,6 +104,7 @@ class Daemon(object): + + log.info("starting tuning") + self._thread = threading.Thread(target=self._thread_code) ++ self._terminate.clear() + self._thread.start() + return True + diff --git a/SOURCES/tuned-2.3.0-handle-root-block-devices.patch b/SOURCES/tuned-2.3.0-handle-root-block-devices.patch new file mode 100644 index 0000000..08a7b15 --- /dev/null +++ b/SOURCES/tuned-2.3.0-handle-root-block-devices.patch @@ -0,0 +1,19 @@ +diff --git a/tuned/plugins/plugin_disk.py b/tuned/plugins/plugin_disk.py +index e799895..6101621 100644 +--- a/tuned/plugins/plugin_disk.py ++++ b/tuned/plugins/plugin_disk.py +@@ -31,10 +31,10 @@ class DiskPlugin(hotplug.Plugin): + self._free_devices = self._devices.copy() + + def _device_is_supported(cls, device): +- return device.device_type == "disk" \ +- and device.attributes.get("removable", None) == "0" \ +- and device.parent is not None \ +- and device.parent.subsystem in ["scsi", "virtio"] ++ return device.device_type == "disk" and \ ++ device.attributes.get("removable", None) == "0" and \ ++ (device.parent is None or \ ++ device.parent.subsystem in ["scsi", "virtio"]) + + def _hardware_events_init(self): + self._hardware_inventory.subscribe(self, "block", self._hardware_events_callback) diff --git a/SOURCES/tuned-2.3.0-latency-performance-thp.patch b/SOURCES/tuned-2.3.0-latency-performance-thp.patch new file mode 100644 index 0000000..28ea6d5 --- /dev/null +++ b/SOURCES/tuned-2.3.0-latency-performance-thp.patch @@ -0,0 +1,32 @@ +From 640e100341fe97c3127598926c126f00c07499f9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= +Date: Fri, 14 Feb 2014 12:41:59 +0100 +Subject: [PATCH 1/4] latency-performance: leaving THP on its default +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: rhbz#1064510 + +Signed-off-by: Jaroslav Škarvada +--- + profiles/latency-performance/tuned.conf | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/profiles/latency-performance/tuned.conf b/profiles/latency-performance/tuned.conf +index 929a556..04abfbe 100644 +--- a/profiles/latency-performance/tuned.conf ++++ b/profiles/latency-performance/tuned.conf +@@ -8,9 +8,6 @@ governor=performance + energy_perf_bias=performance + min_perf_pct=100 + +-[vm] +-transparent_hugepages=never +- + [sysctl] + # ktune sysctl settings for rhel6 servers, maximizing i/o throughput + # +-- +1.8.5.3 + diff --git a/SOURCES/tuned-2.3.0-network-latency.patch b/SOURCES/tuned-2.3.0-network-latency.patch new file mode 100644 index 0000000..c603b59 --- /dev/null +++ b/SOURCES/tuned-2.3.0-network-latency.patch @@ -0,0 +1,58 @@ +From a195fc06fe56ffcbeb2a9ad1a16af7fc38e0ffd5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= +Date: Fri, 14 Feb 2014 13:13:14 +0100 +Subject: [PATCH 3/4] network-latency: added new profile +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: rhbz#1052418 + +Signed-off-by: Jaroslav Škarvada +--- + man/tuned-adm.8 | 6 ++++++ + profiles/network-latency/tuned.conf | 15 +++++++++++++++ + 2 files changed, 21 insertions(+) + create mode 100644 profiles/network-latency/tuned.conf + +diff --git a/man/tuned-adm.8 b/man/tuned-adm.8 +index 443fefe..dfba025 100644 +--- a/man/tuned-adm.8 ++++ b/man/tuned-adm.8 +@@ -111,6 +111,12 @@ CPU governor is set to performance andlocked to the low C states (by PM QoS). + CPU energy performance bias to performance. + + .TP ++.BI network-latency ++Profile for low latency network tuning. It is based on the latency-performance ++profile. It additionaly disables transparent hugepages, NUMA balancing and ++tunes several other network related sysctl parameters. ++ ++.TP + .BI "desktop" + Profile optimized for desktops based on balanced profile. It additionaly + enables scheduler autogroups for better response of interactive applications. +diff --git a/profiles/network-latency/tuned.conf b/profiles/network-latency/tuned.conf +new file mode 100644 +index 0000000..f4ec2de +--- /dev/null ++++ b/profiles/network-latency/tuned.conf +@@ -0,0 +1,15 @@ ++# ++# tuned configuration ++# ++ ++[main] ++include=latency-performance ++ ++[vm] ++transparent_hugepages=never ++ ++[sysctl] ++net.core.busy_read=50 ++net.core.busy_poll=50 ++net.ipv4.tcp_fastopen=3 ++kernel.numa_balancing=0 +-- +1.8.5.3 + diff --git a/SOURCES/tuned-2.3.0-network-throughput.patch b/SOURCES/tuned-2.3.0-network-throughput.patch new file mode 100644 index 0000000..52fe31e --- /dev/null +++ b/SOURCES/tuned-2.3.0-network-throughput.patch @@ -0,0 +1,57 @@ +From 153afc6c9f7663ad083fbb764164e57737f7e4d2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= +Date: Fri, 14 Feb 2014 13:31:21 +0100 +Subject: [PATCH 4/4] network-throughput: added new profile +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: rhbz#1052421 + +Signed-off-by: Jaroslav Škarvada +--- + man/tuned-adm.8 | 5 +++++ + profiles/network-throughput/tuned.conf | 15 +++++++++++++++ + 2 files changed, 20 insertions(+) + create mode 100644 profiles/network-throughput/tuned.conf + +diff --git a/man/tuned-adm.8 b/man/tuned-adm.8 +index dfba025..c2a11a3 100644 +--- a/man/tuned-adm.8 ++++ b/man/tuned-adm.8 +@@ -111,6 +111,11 @@ CPU governor is set to performance andlocked to the low C states (by PM QoS). + CPU energy performance bias to performance. + + .TP ++.BI network-throughput ++Profile for throughput network tuning. It is based on the throughput-performance ++profile. It additionaly increases kernel network buffers. ++ ++.TP + .BI network-latency + Profile for low latency network tuning. It is based on the latency-performance + profile. It additionaly disables transparent hugepages, NUMA balancing and +diff --git a/profiles/network-throughput/tuned.conf b/profiles/network-throughput/tuned.conf +new file mode 100644 +index 0000000..fbc2b72 +--- /dev/null ++++ b/profiles/network-throughput/tuned.conf +@@ -0,0 +1,15 @@ ++# ++# tuned configuration ++# ++ ++[main] ++include=throughput-performance ++ ++[sysctl] ++# Increase kernel buffer size maximums. Currently this seems only necessary at 40Gb speeds. ++# ++# The buffer tuning values below do not account for any potential hugepage allocation. ++# Ensure that you do not oversubscribe system memory. ++net.ipv4.tcp_rmem="4096 87380 16777216" ++net.ipv4.tcp_wmem="4096 16384 16777216" ++net.ipv4.udp_mem="3145728 4194304 16777216" +-- +1.8.5.3 + diff --git a/SOURCES/tuned-2.3.0-no-find.patch b/SOURCES/tuned-2.3.0-no-find.patch new file mode 100644 index 0000000..0dd80e4 --- /dev/null +++ b/SOURCES/tuned-2.3.0-no-find.patch @@ -0,0 +1,20 @@ +commit a47b0e1be74f31d15279aac8ae5b1438932844a2 +Author: Jaroslav Škarvada +Date: Tue Nov 12 14:57:01 2013 +0100 + + spindown-disk: removed useless find, probably typo + + Signed-off-by: Jaroslav Škarvada + +diff --git a/profiles/spindown-disk/script.sh b/profiles/spindown-disk/script.sh +index fa2d389..5ee40dd 100755 +--- a/profiles/spindown-disk/script.sh ++++ b/profiles/spindown-disk/script.sh +@@ -12,7 +12,6 @@ start() { + disable_logs_syncing + + remount_partitions commit=600,noatime $EXT_PARTITIONS +- find /etc/ &> /dev/null + sync + + return 0 diff --git a/SOURCES/tuned-2.3.0-runtime-profile-autodetection.patch b/SOURCES/tuned-2.3.0-runtime-profile-autodetection.patch new file mode 100644 index 0000000..0d838ee --- /dev/null +++ b/SOURCES/tuned-2.3.0-runtime-profile-autodetection.patch @@ -0,0 +1,49 @@ +diff --git a/tuned/daemon/daemon.py b/tuned/daemon/daemon.py +index 35f60c2..029e311 100644 +--- a/tuned/daemon/daemon.py ++++ b/tuned/daemon/daemon.py +@@ -1,4 +1,5 @@ + import os ++import errno + import threading + import tuned.logs + from tuned.exceptions import TunedException +@@ -105,16 +106,34 @@ class Daemon(object): + def _save_active_profile(self, profile_name): + try: + with open(consts.ACTIVE_PROFILE_FILE, "w") as f: +- f.write(profile_name) ++ f.write(profile_name + "\n") + except (OSError,IOError) as e: + log.error("Cannot write active profile into %s: %s" % (consts.ACTIVE_PROFILE_FILE, str(e))) + ++ def _set_recommended_profile(self): ++ log.info("no profile preset, checking what is recommended for your configuration") ++ profile = tuned.utils.commands.recommend_profile() ++ log.info("using '%s' profile and setting it as active" % profile) ++ self._save_active_profile(profile) ++ return profile ++ + def _get_active_profile(self): + try: + with open(consts.ACTIVE_PROFILE_FILE, "r") as f: +- return f.read().strip() +- except (OSError, IOError, EOFError) as e: +- log.error("Cannot read active profile, setting default.") ++ profile = f.read().strip() ++ if profile == "": ++ profile = self._set_recommended_profile() ++ return profile ++ except IOError as e: ++ if e.errno == errno.ENOENT: ++ # No such file or directory ++ profile = self._set_recommended_profile() ++ else: ++ profile = consts.DEFAULT_PROFILE ++ log.error("error reading active profile from '%s', falling back to '%s' profile" % (consts.ACTIVE_PROFILE_FILE, profile)) ++ return profile ++ except (OSError, EOFError) as e: ++ log.error("cannot read active profile, falling back to '%s' profile" % consts.DEFAULT_PROFILE) + return consts.DEFAULT_PROFILE + + def is_enabled(self): diff --git a/SOURCES/tuned-2.3.0-throughput-performance-on-server.patch b/SOURCES/tuned-2.3.0-throughput-performance-on-server.patch new file mode 100644 index 0000000..37337d7 --- /dev/null +++ b/SOURCES/tuned-2.3.0-throughput-performance-on-server.patch @@ -0,0 +1,13 @@ +diff --git a/recommend.conf b/recommend.conf +index 7a45523..d01ebdf 100644 +--- a/recommend.conf ++++ b/recommend.conf +@@ -9,7 +9,7 @@ + + [throughput-performance] + virt= +-system=.*computenode.* ++system=.*(computenode|server).* + + [virtual-guest] + virt=.+ diff --git a/SOURCES/tuned-2.3.0-timing-improvements.patch b/SOURCES/tuned-2.3.0-timing-improvements.patch new file mode 100644 index 0000000..7d9bd97 --- /dev/null +++ b/SOURCES/tuned-2.3.0-timing-improvements.patch @@ -0,0 +1,139 @@ +diff --git a/man/tuned-main.conf.5 b/man/tuned-main.conf.5 +index 61a6a4b..6f324be 100644 +--- a/man/tuned-main.conf.5 ++++ b/man/tuned-main.conf.5 +@@ -16,17 +16,31 @@ will be used. Please note if it is enabled here, it is still possible + to individually disable it in plugins. + + .TP ++.BI sleep_interval= INT ++Tuned daemon is periodically waken after \fIINT\fR seconds and checks ++for events. By default this is set to 1 second. If you have Python 2 ++interpreter with applied patch from Red Hat Bugzilla #917709 this ++controls responsiveness time of Tuned to commands (i.e. if you ++request profile switch, it may take up to 1 second until Tuned reacts). ++Increase this number for higher responsiveness times and more power ++savings (due to lower number of wakeups). In case you have unpatched ++Python 2 interpreter, this settings will have no visible effect, ++because the intepreter will poll 20 times per second. ++ ++.TP + .BI update_interval= INT + Update interval for dynamic tuning (in seconds). Tuned daemon is periodically + waken after \fIINT\fR seconds, updates its monitors, calculates new tuning + parameters for enabled plugins and applies the changes. Plugins that have + disabled dynamic tuning are not processed. By default the \fIINT\fR is set + to 10 seconds. Tuned daemon doesn't periodically wake if dynamic tuning is +-globally disabled (see \fBdynamic_tuning\fR). ++globally disabled (see \fBdynamic_tuning\fR) or this setting set to 0. ++This must be multiple of \fBsleep_interval\fR. + + .SH EXAMPLE + .nf + dynamic_tuning = 1 ++sleep_interval = 1 + update_interval = 10 + .fi + +diff --git a/tuned/consts.py b/tuned/consts.py +index 1dd53ab..6c8dc4b 100644 +--- a/tuned/consts.py ++++ b/tuned/consts.py +@@ -18,5 +18,7 @@ SYSTEM_RELEASE_FILE = "/etc/system-release-cpe" + + # default configuration + CFG_DEF_DYNAMIC_TUNING = True ++# how long to sleep before checking for events (in seconds) ++CFG_DEF_SLEEP_INTERVAL = 1 + # update interval for dynamic tuning (in seconds) + CFG_DEF_UPDATE_INTERVAL = 10 +diff --git a/tuned/daemon/application.py b/tuned/daemon/application.py +index f1b5208..e4c9da3 100644 +--- a/tuned/daemon/application.py ++++ b/tuned/daemon/application.py +@@ -16,6 +16,7 @@ log = tuned.logs.get() + __all__ = ["Application"] + + global_config_spec = ["dynamic_tuning = boolean(default=%s)" % consts.CFG_DEF_DYNAMIC_TUNING, ++ "sleep_interval = integer(default=%s)" % consts.CFG_DEF_SLEEP_INTERVAL, + "update_interval = integer(default=%s)" % consts.CFG_DEF_UPDATE_INTERVAL] + + class Application(object): +@@ -31,7 +32,6 @@ class Application(object): + self.config = self._load_global_config() + if self.config.get("dynamic_tuning"): + log.info("dynamic tuning is enabled (can be overriden in plugins)") +- log.info("update interval is %d seconds" % self.config.get("update_interval")) + else: + log.info("dynamic tuning is globally disabled") + +@@ -44,7 +44,7 @@ class Application(object): + profile_loader = profiles.Loader(profile_locator, profile_factory, profile_merger) + + +- self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, int(self.config.get("update_interval", consts.CFG_DEF_UPDATE_INTERVAL))) ++ self._daemon = daemon.Daemon(unit_manager, profile_loader, profile_name, self.config) + self._controller = controller.Controller(self._daemon) + + self._dbus_exporter = None +diff --git a/tuned/daemon/daemon.py b/tuned/daemon/daemon.py +index 804ac0b..35f60c2 100644 +--- a/tuned/daemon/daemon.py ++++ b/tuned/daemon/daemon.py +@@ -9,9 +9,27 @@ log = tuned.logs.get() + + + class Daemon(object): +- def __init__(self, unit_manager, profile_loader, profile_name=None, update_interval = int(consts.CFG_DEF_UPDATE_INTERVAL)): ++ def __init__(self, unit_manager, profile_loader, profile_name=None, config=None): + log.debug("initializing daemon") +- self._update_interval = update_interval ++ 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 ++ if config is not None: ++ self._sleep_interval = int(config.get("sleep_interval", consts.CFG_DEF_SLEEP_INTERVAL)) ++ self._update_interval = int(config.get("update_interval", consts.CFG_DEF_UPDATE_INTERVAL)) ++ self._dynamic_tuning = config.get("dynamic_tuning", consts.CFG_DEF_DYNAMIC_TUNING) ++ if self._sleep_interval <= 0: ++ self._sleep_interval = int(consts.CFG_DEF_SLEEP_INTERVAL) ++ if self._update_interval == 0: ++ self._dynamic_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 overriden by plugins)") ++ 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._unit_manager = unit_manager + self._profile_loader = profile_loader + self._init_threads() +@@ -65,11 +83,21 @@ class Daemon(object): + self._save_active_profile(self._profile.name) + self._unit_manager.start_tuning() + +- while not tuned.utils.commands.wait(self._terminate, self._update_interval): +- log.debug("updating monitors") +- self._unit_manager.update_monitors() +- log.debug("performing tunings") +- self._unit_manager.update_tuning() ++ # In python 2 interpreter with applied patch for rhbz#917709 we need to periodically ++ # poll, otherwise the python will not have chance to update events / locks (due to GIL) ++ # and e.g. DBus control will not work. The polling interval of 1 seconds (which is ++ # the default) is still much better than 50 ms polling with unpatched interpreter. ++ # For more details see tuned rhbz#917587. ++ _sleep_cnt = self._sleep_cycles ++ while not tuned.utils.commands.wait(self._terminate, self._sleep_interval): ++ if self._dynamic_tuning: ++ _sleep_cnt -= 1 ++ if _sleep_cnt <= 0: ++ _sleep_cnt = self._sleep_cycles ++ log.debug("updating monitors") ++ self._unit_manager.update_monitors() ++ log.debug("performing tunings") ++ self._unit_manager.update_tuning() + + self._unit_manager.stop_tuning() + self._unit_manager.destroy_all() diff --git a/SPECS/tuned.spec b/SPECS/tuned.spec new file mode 100644 index 0000000..7576223 --- /dev/null +++ b/SPECS/tuned.spec @@ -0,0 +1,390 @@ +Summary: A dynamic adaptive system tuning daemon +Name: tuned +Version: 2.3.0 +Release: 16%{?dist} +License: GPLv2+ +Source: https://fedorahosted.org/releases/t/u/tuned/tuned-%{version}.tar.bz2 +URL: https://fedorahosted.org/tuned/ +BuildArch: noarch +BuildRequires: python, systemd +Requires(post): systemd, virt-what +Requires(preun): systemd +Requires(postun): systemd +Requires: python-decorator, dbus-python, pygobject3-base, python-pyudev +Requires: virt-what, python-configobj, ethtool, gawk +Patch0: tuned-2.3.0-fix-race.patch +Patch1: tuned-2.3.0-timing-improvements.patch +Patch2: tuned-2.3.0-no-find.patch +Patch3: tuned-2.3.0-dirty-ratios.patch +Patch4: tuned-2.3.0-throughput-performance-on-server.patch +Patch5: tuned-2.3.0-latency-performance-thp.patch +Patch6: tuned-2.3.0-network-latency.patch +Patch7: tuned-2.3.0-network-throughput.patch +Patch8: tuned-2.3.0-cpupower-conflict.patch +Patch9: tuned-2.3.0-handle-root-block-devices.patch +Patch10: tuned-2.3.0-assignment-modifiers.patch +Patch11: tuned-2.3.0-atomic.patch +Patch12: tuned-2.3.0-runtime-profile-autodetection.patch + +%description +The tuned package contains a daemon that tunes system settings dynamically. +It does so by monitoring the usage of several system components periodically. +Based on that information components will then be put into lower or higher +power saving modes to adapt to the current usage. Currently only ethernet +network and ATA harddisk devices are implemented. + +%package utils +Requires: %{name} = %{version}-%{release} +Summary: Various tuned utilities +Requires: powertop + +%description utils +This package contains utilities that can help you to fine tune and +debug your system and manage tuned profiles. + +%package utils-systemtap +Summary: Disk and net statistic monitoring systemtap scripts +Requires: %{name} = %{version}-%{release} +Requires: systemtap + +%description utils-systemtap +This package contains several systemtap scripts to allow detailed +manual monitoring of the system. Instead of the typical IO/sec it collects +minimal, maximal and average time between operations to be able to +identify applications that behave power inefficient (many small operations +instead of fewer large ones). + +%package profiles-atomic +Summary: Additional tuned profiles targeted to Atomic +Requires: %{name} = %{version}-%{release} + +%description profiles-atomic +Additional tuned profiles targeted to Atomic host and guest. + +%package profiles-compat +Summary: Additional tuned profiles mainly for backward compatibility with tuned 1.0 +Requires: %{name} = %{version}-%{release} + +%description profiles-compat +Additional tuned profiles mainly for backward compatibility with tuned 1.0. +It can be also used to fine tune your system for specific scenarios. + +%prep +%setup -q +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 + + +%build + + +%install +make install DESTDIR=%{buildroot} +%if 0%{?rhel} +sed -i 's/\(dynamic_tuning[ \t]*=[ \t]*\).*/\10/' %{buildroot}%{_sysconfdir}/tuned/tuned-main.conf +%endif + + +%post +%systemd_post tuned.service + +# convert active_profile from full path to name (if needed) +sed -i 's|.*/\([^/]\+\)/[^\.]\+\.conf|\1|' /etc/tuned/active_profile + + +%preun +%systemd_preun tuned.service + + +%postun +%systemd_postun_with_restart tuned.service + + +%triggerun -- tuned < 2.0-0 +# remove ktune from old tuned, now part of tuned +/usr/sbin/service ktune stop &>/dev/null || : +/usr/sbin/chkconfig --del ktune &>/dev/null || : + + +%files +%defattr(-,root,root,-) +%doc AUTHORS +%doc COPYING +%doc README +%doc doc/TIPS.txt +%{_sysconfdir}/bash_completion.d +%{python_sitelib}/tuned +%{_sbindir}/tuned +%{_sbindir}/tuned-adm +%exclude %{_prefix}/lib/tuned/default +%exclude %{_prefix}/lib/tuned/desktop-powersave +%exclude %{_prefix}/lib/tuned/laptop-ac-powersave +%exclude %{_prefix}/lib/tuned/server-powersave +%exclude %{_prefix}/lib/tuned/laptop-battery-powersave +%exclude %{_prefix}/lib/tuned/enterprise-storage +%exclude %{_prefix}/lib/tuned/spindown-disk +%exclude %{_prefix}/lib/tuned/atomic-host +%exclude %{_prefix}/lib/tuned/atomic-guest +%{_prefix}/lib/tuned +%dir %{_sysconfdir}/tuned +%config(noreplace) %{_sysconfdir}/tuned/active_profile +%config(noreplace) %{_sysconfdir}/tuned/tuned-main.conf +%{_sysconfdir}/tmpfiles.d +%{_sysconfdir}/dbus-1/system.d/com.redhat.tuned.conf +%{_unitdir}/tuned.service +%dir %{_localstatedir}/log/tuned +%dir /run/tuned +%{_mandir}/man5/tuned* +%{_mandir}/man8/tuned* + +%files utils +%defattr(-,root,root,-) +%doc COPYING +%{_bindir}/powertop2tuned +%{_libexecdir}/tuned/pmqos-static* + +%files utils-systemtap +%defattr(-,root,root,-) +%doc doc/README.utils +%doc doc/README.scomes +%doc COPYING +%{_sbindir}/varnetload +%{_sbindir}/netdevstat +%{_sbindir}/diskdevstat +%{_sbindir}/scomes +%{_mandir}/man8/varnetload.* +%{_mandir}/man8/netdevstat.* +%{_mandir}/man8/diskdevstat.* +%{_mandir}/man8/scomes.* + +%files profiles-atomic +%defattr(-,root,root,-) +%{_prefix}/lib/tuned/atomic-host +%{_prefix}/lib/tuned/atomic-guest + +%files profiles-compat +%defattr(-,root,root,-) +%{_prefix}/lib/tuned/default +%{_prefix}/lib/tuned/desktop-powersave +%{_prefix}/lib/tuned/laptop-ac-powersave +%{_prefix}/lib/tuned/server-powersave +%{_prefix}/lib/tuned/laptop-battery-powersave +%{_prefix}/lib/tuned/enterprise-storage +%{_prefix}/lib/tuned/spindown-disk + +%changelog +* Fri Sep 19 2014 Jaroslav Škarvada - 2.3.0-16 +- autodetecting initial profile in runtime, not int post install + resolves: rhbz#1144067 + +* Tue Sep 2 2014 Jaroslav Škarvada - 2.3.0-15 +- updated man page to include atomic-host and atomic-guest profiles + related: rhbz#1091977, rhbz#1091979 + +* Wed Aug 27 2014 Jaroslav Škarvada - 2.3.0-14 +- add atomic-host and atomic-guest profiles + resolves: rhbz#1091977, rhbz#1091979 + +* Mon May 12 2014 Jaroslav Škarvada - 2.3.0-13 +- add support for assignment modifiers + resolves: rhbz#1096917 + +* Wed May 7 2014 Jaroslav Škarvada - 2.3.0-12 +- handle root block devices + resolves: rhbz#1033251 + +* Fri Mar 7 2014 Jaroslav Škarvada - 2.3.0-11 +- reverted fix for bug 1073008, dependency is not met on s390 + related: rhbz#1073008 + +* Thu Mar 6 2014 Jaroslav Škarvada - 2.3.0-10 +- added requirement to kernel-tools + resolves: rhbz#1073008 +- made cpupower.service conflicting + resolves: rhbz#1073392 + +* Tue Mar 4 2014 Jaroslav Škarvada - 2.3.0-9 +- re-arranged profile autoselection patches for better maintainability + related: rhbz#1069123 + +* Mon Mar 3 2014 Jaroslav Škarvada - 2.3.0-8 +- fixed profile autoselection + resolves: rhbz#1069123 + +* Fri Feb 14 2014 Jaroslav Škarvada - 2.3.0-7 +- throughput-performance is default for the server + resolves: rhbz#1063481 +- THP not disabled in the latency-performance profile + resolves: rhbz#1064510 +- added network-latency profile + resolves: rhbz#1052418 +- added network-throughput profile + resolves: rhbz#1052421 + +* Tue Jan 7 2014 Jaroslav Škarvada - 2.3.0-6 +- altered dirty ratios of troughput-performance for better performance + resolves: rhbz#1043533 + +* Fri Dec 27 2013 Daniel Mach - 2.3.0-5 +- Mass rebuild 2013-12-27 + +* Fri Nov 22 2013 Jaroslav Škarvada - 2.3.0-4 +- removed useless find from the spindown-disk profile + resolves: rhbz#1030439 + +* Fri Nov 8 2013 Jaroslav Škarvada - 2.3.0-3 +- defuzzified patches + related: rhbz#1028119, rhbz#1028122 + +* Fri Nov 8 2013 Jaroslav Škarvada - 2.3.0-2 +- fixed race condition in the start/stop code + resolves: rhbz#1028119 +- improved tuned responsiveness + resolves: rhbz#1028122 + +* Wed Nov 6 2013 Jaroslav Škarvada - 2.3.0-1 +- new-release + resolves: rhbz#1020743 + - audio plugin: fixed audio settings in standard profiles + - video plugin: fixed tunings + - daemon: fixed crash if preset profile is not available + - man: various updates and corrections + - functions: fixed usb and bluetooth handling + - tuned: switched to lightweighted pygobject3-base + - daemon: added global config for dynamic_tuning + - utils: added pmqos-static script for debug purposes + - throughput-performance: various fixes + - tuned: added global option update_interval + - plugin_cpu: added support for x86_energy_perf_policy + resolves: rhbz#1015675 + - dbus: fixed KeyboardInterrupt handling + - plugin_cpu: added support for intel_pstate + resolves: rhbz#996722 + - profiles: various fixes + - profiles: added desktop profile + resolves: rhbz#996723 + - tuned-adm: implemented non DBus fallback control + - profiles: added sap profile + - tuned: lowered CPU usage due to python bug + +* Wed Oct 16 2013 Jaroslav Škarvada - 2.2.2-4 +- lock CPU to C1 instead of C0 in latency-performance profile + resolves: rhbz#1013085 +- readahed multiply set to 4 in throughput-performance profile + resolves: rhbz#987570 +- packaged pmqos-static script for debugging purposes + resolves: rhbz#1015676 +- added global configuration file with the possibility to globally + disable the dynamic tuning and it is by default disabled on RHEL + resolves: rhbz#1006427 + +* Thu Jul 25 2013 Jaroslav Škarvada - 2.2.2-3 +- do not package backup file + related: rhbz#986468 + +* Thu Jul 25 2013 Jaroslav Škarvada - 2.2.2-2 +- used pygobject3-base instead of pygobject2 + resolves: rhbz#986468 + +* Tue Mar 19 2013 Jaroslav Škarvada - 2.2.2-1 +- new-release: + - cpu plugin: fixed cpupower workaround + - cpu plugin: fixed crash if cpupower is installed + +* Fri Mar 1 2013 Jaroslav Škarvada - 2.2.1-1 +- new release: + - audio plugin: fixed error handling in _get_timeout + - removed cpupower dependency, added sysfs fallback + - powertop2tuned: fixed parser crash on binary garbage + resolves: rhbz#914933 + - cpu plugin: dropped multicore_powersave as kernel upstream already did + - plugins: options manipulated by dynamic tuning are now correctly saved and restored + - powertop2tuned: added alias -e for --enable option + - powertop2tuned: new option -m, --merge-profile to select profile to merge + - prefer transparent_hugepage over redhat_transparent_hugepage + - recommend: use recommend.conf not autodetect.conf + - tuned.service: switched to dbus type service + resolves: rhbz#911445 + - tuned: new option --pid, -P to write PID file + - tuned, tuned-adm: added new option --version, -v to show version + - disk plugin: use APM value 254 for cleanup / APM disable instead of 255 + resolves: rhbz#905195 + - tuned: new option --log, -l to select log file + - powertop2tuned: avoid circular deps in include (one level check only) + - powertop2tuned: do not crash if powertop is not installed + - net plugin: added support for wake_on_lan static tuning + resolves: rhbz#885504 + - loader: fixed error handling + - spec: used systemd-rpm macros + resolves: rhbz#850347 + +* Mon Jan 28 2013 Jan Vcelak 2.2.0-1 +- new release: + - remove nobarrier from virtual-guest (data loss prevention) + - devices enumeration via udev, instead of manual retrieval + - support for dynamically inserted devices (currently disk plugin) + - dropped rfkill plugins (bluetooth and wifi), the code didn't work + +* Wed Jan 2 2013 Jaroslav Škarvada - 2.1.2-1 +- new release: + - systemtap {disk,net}devstat: fix typo in usage + - switched to configobj parser + - latency-performance: disabled THP + - fixed fd leaks on subprocesses + +* Thu Dec 06 2012 Jan Vcelak 2.1.1-1 +- fix: powertop2tuned execution +- fix: ownership of /etc/tuned + +* Mon Dec 03 2012 Jan Vcelak 2.1.0-1 +- new release: + - daemon: allow running without selected profile + - daemon: fix profile merging, allow only safe characters in profile names + - daemon: implement missing methods in DBus interface + - daemon: implement profile recommendation + - daemon: improve daemonization, PID file handling + - daemon: improved device matching in profiles, negation possible + - daemon: various internal improvements + - executables: check for EUID instead of UID + - executables: run python with -Es to increase security + - plugins: cpu - fix cpupower execution + - plugins: disk - fix option setting + - plugins: mounts - new, currently supports only barriers control + - plugins: sysctl - fix a bug preventing settings application + - powertop2tuned: speedup, fix crashes with non-C locales + - powertop2tuned: support for powertop 2.2 output + - profiles: progress on replacing scripts with plugins + - tuned-adm: bash completion - suggest profiles from all supported locations + - tuned-adm: complete switch to D-bus + - tuned-adm: full control to users with physical access + +* Mon Oct 08 2012 Jaroslav Škarvada - 2.0.2-1 +- New version +- Systemtap scripts moved to utils-systemtap subpackage + +* Sun Jul 22 2012 Fedora Release Engineering - 2.0.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jun 12 2012 Jaroslav Škarvada - 2.0.1-3 +- another powertop-2.0 compatibility fix + Resolves: rhbz#830415 + +* Tue Jun 12 2012 Jan Kaluza - 2.0.1-2 +- fixed powertop2tuned compatibility with powertop-2.0 + +* Tue Apr 03 2012 Jaroslav Škarvada - 2.0.1-1 +- new version + +* Fri Mar 30 2012 Jan Vcelak 2.0-1 +- first stable release