diff --git a/.gitignore b/.gitignore
index 05be9b3..62850fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/tuned-2.10.0.tar.gz
+SOURCES/tuned-2.12.0.tar.gz
diff --git a/.tuned.metadata b/.tuned.metadata
index 8c2c6b0..0ace498 100644
--- a/.tuned.metadata
+++ b/.tuned.metadata
@@ -1 +1 @@
-24ecb366bf503d8f6a79ced3f8faf239c81ad8cf SOURCES/tuned-2.10.0.tar.gz
+e28eeb10b3389ff1eae07af83befbf1d69f4661b SOURCES/tuned-2.12.0.tar.gz
diff --git a/SOURCES/0001-Make-python-dmidecode-a-weak-dependency.patch b/SOURCES/0001-Make-python-dmidecode-a-weak-dependency.patch
deleted file mode 100644
index 6351d3b..0000000
--- a/SOURCES/0001-Make-python-dmidecode-a-weak-dependency.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From df1ce7287ad373694193d79a7843e4e054d40848 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
-Date: Wed, 10 Oct 2018 14:26:51 +0200
-Subject: [PATCH] Make python-dmidecode a weak dependency
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-It's only available on x86_64.
-
-Resolves: rhbz#1565598
-
-Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
----
- tuned.spec              |  4 ++--
- tuned/utils/commands.py | 19 +++++++++++++------
- 2 files changed, 15 insertions(+), 8 deletions(-)
-
-diff --git a/tuned.spec b/tuned.spec
-index 3bf0db2..9cd74e1 100644
---- a/tuned.spec
-+++ b/tuned.spec
-@@ -57,10 +57,10 @@ Requires: %{_py}-schedutils, %{_py}-linux-procfs, %{_py}-perf
- # requires for packages with inconsistent python2/3 names
- %if %{with python3}
- Requires: python3-dbus, python3-gobject-base
--Requires: python3-dmidecode
-+Recommends: python3-dmidecode
- %else
- Requires: dbus-python, pygobject3-base
--Requires: python-dmidecode
-+Recommends: python-dmidecode
- %endif
- Requires: virt-what, ethtool, gawk, hdparm
- Requires: util-linux, dbus, polkit
-diff --git a/tuned/utils/commands.py b/tuned/utils/commands.py
-index 9634709..5692450 100644
---- a/tuned/utils/commands.py
-+++ b/tuned/utils/commands.py
-@@ -9,7 +9,11 @@ import re
- import procfs
- from subprocess import *
- from tuned.exceptions import TunedException
--import dmidecode
-+try:
-+	import dmidecode
-+	have_dmidecode = True
-+except:
-+	have_dmidecode = False
- try:
- 	import syspurpose.files
- 	have_syspurpose = True
-@@ -420,12 +424,15 @@ class commands:
- 						if len(ps.find_by_regex(re.compile(value))) == 0:
- 							match = False
- 					elif option == "chassis_type":
--						for chassis in dmidecode.chassis().values():
--							chassis_type = chassis["data"]["Type"].decode("ascii")
--							if re.match(value, chassis_type, re.IGNORECASE):
--								break
-+						if have_dmidecode:
-+							for chassis in dmidecode.chassis().values():
-+								chassis_type = chassis["data"]["Type"].decode("ascii")
-+								if re.match(value, chassis_type, re.IGNORECASE):
-+									break
-+							else:
-+								match = False
- 						else:
--							match = False
-+							log.debug("Ignoring 'chassis_type' in '%s', dmidecode is not available." % fname)
- 					elif option == "syspurpose_role":
- 						if have_syspurpose:
- 							s = syspurpose.files.SyspurposeStore(
--- 
-2.17.1
-
diff --git a/SOURCES/0001-Support-chassis-type-matching-in-recommend.conf.patch b/SOURCES/0001-Support-chassis-type-matching-in-recommend.conf.patch
deleted file mode 100644
index 49b92d8..0000000
--- a/SOURCES/0001-Support-chassis-type-matching-in-recommend.conf.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From 469a86250168ab51287b2e2c3d88efc1c8edec7e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
-Date: Tue, 7 Aug 2018 17:07:49 +0200
-Subject: [PATCH 1/2] Support chassis type matching in recommend.conf
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves: rhbz#1565598
-
-Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
----
- Makefile                | 4 +++-
- tuned.spec              | 2 ++
- tuned/utils/commands.py | 8 ++++++++
- 3 files changed, 13 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index f302db1..816fcb1 100644
---- a/Makefile
-+++ b/Makefile
-@@ -212,6 +212,8 @@ test:
- 	$(PYTHON) -m unittest discover tests
- 
- lint:
--	$(PYLINT) -E -f parseable tuned *.py
-+	# --ignore commands.py is a workaround for
-+	# https://bugzilla.redhat.com/show_bug.cgi?id=1613466
-+	$(PYLINT) --ignore commands.py -E -f parseable tuned *.py
- 
- .PHONY: clean archive srpm tag test lint
-diff --git a/tuned.spec b/tuned.spec
-index ed4c4f0..2b4f039 100644
---- a/tuned.spec
-+++ b/tuned.spec
-@@ -57,8 +57,10 @@ Requires: %{_py}-schedutils, %{_py}-linux-procfs, %{_py}-perf
- # requires for packages with inconsistent python2/3 names
- %if %{with python3}
- Requires: python3-dbus, python3-gobject-base
-+Requires: python3-dmidecode
- %else
- Requires: dbus-python, pygobject3-base
-+Requires: python-dmidecode
- %endif
- Requires: virt-what, ethtool, gawk, hdparm
- Requires: util-linux, dbus, polkit
-diff --git a/tuned/utils/commands.py b/tuned/utils/commands.py
-index 41d6d99..8bb31a3 100644
---- a/tuned/utils/commands.py
-+++ b/tuned/utils/commands.py
-@@ -9,6 +9,7 @@ import re
- import procfs
- from subprocess import *
- from tuned.exceptions import TunedException
-+import dmidecode
- 
- log = tuned.logs.get()
- 
-@@ -413,6 +414,13 @@ class commands:
- 						ps.reload_threads()
- 						if len(ps.find_by_regex(re.compile(value))) == 0:
- 							match = False
-+					elif option == "chassis_type":
-+						for chassis in dmidecode.chassis().values():
-+							chassis_type = chassis["data"]["Type"].decode("ascii")
-+							if re.match(value, chassis_type, re.IGNORECASE):
-+								break
-+						else:
-+							match = False
- 				if match:
- 					# remove the ",.*" suffix
- 					r = re.compile(r",[^,]*$")
--- 
-2.17.1
-
diff --git a/SOURCES/0001-plugin_disk-Fix-checking-the-removable-attribute-on-.patch b/SOURCES/0001-plugin_disk-Fix-checking-the-removable-attribute-on-.patch
deleted file mode 100644
index 49ce5ab..0000000
--- a/SOURCES/0001-plugin_disk-Fix-checking-the-removable-attribute-on-.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 2cc3d747986837d7e7957f5a4baede2dd691348a Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
-Date: Thu, 24 Jan 2019 16:28:24 +0100
-Subject: [PATCH] plugin_disk: Fix checking the 'removable' attribute on
- python3
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The 'removable' attribute is a bytestring, so it will never be equal to
-"0" in python3. Check equality with b"0" instead.
-
-The patch was originally written by Tomáš Korbař.
-
-Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
----
- tuned/plugins/plugin_disk.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tuned/plugins/plugin_disk.py b/tuned/plugins/plugin_disk.py
-index 1de1257..65504d8 100644
---- a/tuned/plugins/plugin_disk.py
-+++ b/tuned/plugins/plugin_disk.py
-@@ -39,7 +39,7 @@ class DiskPlugin(hotplug.Plugin):
- 	@classmethod
- 	def _device_is_supported(cls, device):
- 		return  device.device_type == "disk" and \
--			device.attributes.get("removable", None) == "0" and \
-+			device.attributes.get("removable", None) == b"0" and \
- 			(device.parent is None or \
- 					device.parent.subsystem in ["scsi", "virtio", "xen"])
- 
--- 
-2.20.1
-
diff --git a/SOURCES/0001-scheduler-Keep-polling-file-objects-alive-long-enoug.patch b/SOURCES/0001-scheduler-Keep-polling-file-objects-alive-long-enoug.patch
deleted file mode 100644
index 9b4d661..0000000
--- a/SOURCES/0001-scheduler-Keep-polling-file-objects-alive-long-enoug.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From a54b35c3b0c3b228eb924ed4ebfb964eead86cca Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
-Date: Fri, 14 Dec 2018 13:13:58 +0100
-Subject: [PATCH] scheduler: Keep polling file objects alive long enough
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Make sure the file objects returned by evlist.get_pollfd()
-don't go out of scope and get destroyed too soon. This is
-a workaround for python3-perf rhbz#1659445.
-
-Resolves: rhbz#1659140
-
-Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
----
- tuned/plugins/plugin_scheduler.py | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/tuned/plugins/plugin_scheduler.py b/tuned/plugins/plugin_scheduler.py
-index 93b6d91..22e49d3 100644
---- a/tuned/plugins/plugin_scheduler.py
-+++ b/tuned/plugins/plugin_scheduler.py
-@@ -448,7 +448,11 @@ class SchedulerPlugin(base.Plugin):
- 	def _thread_code(self, instance):
- 		r = self._cmd.re_lookup_compile(instance._sched_lookup)
- 		poll = select.poll()
--		for fd in instance._evlist.get_pollfd():
-+		# Store the file objects in a local variable so that they don't
-+		# go out of scope too soon. This is a workaround for
-+		# python3-perf bug rhbz#1659445.
-+		fds = instance._evlist.get_pollfd()
-+		for fd in fds:
- 			poll.register(fd)
- 		while not instance._terminate.is_set():
- 			# timeout to poll in milliseconds
--- 
-2.17.2
-
diff --git a/SOURCES/0001-tuned-adm-Fix-a-traceback-when-run-without-action-sp.patch b/SOURCES/0001-tuned-adm-Fix-a-traceback-when-run-without-action-sp.patch
deleted file mode 100644
index 208e24f..0000000
--- a/SOURCES/0001-tuned-adm-Fix-a-traceback-when-run-without-action-sp.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 6678c472abbd5f645dbb99ab2946c0e35ded7499 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
-Date: Tue, 10 Jul 2018 00:24:00 +0200
-Subject: [PATCH] tuned-adm: Fix a traceback when run without action specified
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Running tuned-adm without an action specified using Python 3 results
-in a traceback. This is because in this case parse_args does not
-exit with a usage message in Python 3 and the 'action' option
-is then undefined.
-
-Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
----
- tuned-adm.py | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/tuned-adm.py b/tuned-adm.py
-index 1b9623d..1df8cc3 100755
---- a/tuned-adm.py
-+++ b/tuned-adm.py
-@@ -100,7 +100,11 @@ if __name__ == "__main__":
- 	debug = options.pop("debug")
- 	asynco = options.pop("async")
- 	timeout = options.pop("timeout")
--	action_name = options.pop("action")
-+	try:
-+		action_name = options.pop("action")
-+	except KeyError:
-+		parser.print_usage(file = sys.stderr)
-+		sys.exit(1)
- 	log_level = options.pop("loglevel")
- 	result = False
- 
--- 
-2.14.4
-
diff --git a/SOURCES/0001-tuned-gui-Sort-plugins-based-on-their-name.patch b/SOURCES/0001-tuned-gui-Sort-plugins-based-on-their-name.patch
deleted file mode 100644
index c2d146d..0000000
--- a/SOURCES/0001-tuned-gui-Sort-plugins-based-on-their-name.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From d46834808c3226b3a6e48649df65befc399c21cd Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
-Date: Wed, 11 Jul 2018 00:41:45 +0200
-Subject: [PATCH] tuned-gui: Sort plugins based on their name
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Previously the sorting was done by comparing the objects themselves,
-which is not what we want and it doesn't work in Python 3 - TypeError
-is raised, e.g:
-TypeError: '<' not supported between instances of 'BootloaderPlugin' and 'MountsPlugin'
-
-Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
----
- tuned-gui.py | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/tuned-gui.py b/tuned-gui.py
-index 8f72fd5..e486687 100755
---- a/tuned-gui.py
-+++ b/tuned-gui.py
-@@ -278,7 +278,8 @@ class Base(object):
- 		self.treestore_profiles = Gtk.ListStore(GObject.TYPE_STRING,
- 				GObject.TYPE_STRING)
- 		self.treestore_plugins = Gtk.ListStore(GObject.TYPE_STRING)
--		for plugin in sorted(self.plugin_loader.plugins):
-+		for plugin in sorted(self.plugin_loader.plugins,
-+				key = lambda plugin: plugin.name):
- 			self.treestore_plugins.append([plugin.name])
- 		self.combobox_plugins = \
- 			self.builder.get_object('comboboxPlugins')
--- 
-2.14.4
-
diff --git a/SOURCES/0002-Support-syspurpose-role-matching-in-recommend.conf.patch b/SOURCES/0002-Support-syspurpose-role-matching-in-recommend.conf.patch
deleted file mode 100644
index 317aca4..0000000
--- a/SOURCES/0002-Support-syspurpose-role-matching-in-recommend.conf.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-From 9efd6d77283324ed8b8802431522a7a4eabd9aa0 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
-Date: Fri, 10 Aug 2018 16:17:47 +0200
-Subject: [PATCH 2/2] Support syspurpose role matching in recommend.conf
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves: rhbz#1565598
-
-Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
----
- tuned.spec              |  3 +++
- tuned/utils/commands.py | 22 ++++++++++++++++++++++
- 2 files changed, 25 insertions(+)
-
-diff --git a/tuned.spec b/tuned.spec
-index 2b4f039..3bf0db2 100644
---- a/tuned.spec
-+++ b/tuned.spec
-@@ -67,6 +67,9 @@ Requires: util-linux, dbus, polkit
- %if 0%{?fedora} > 22 || 0%{?rhel} > 7
- Recommends: kernel-tools
- %endif
-+%if 0%{?rhel} > 7
-+Requires: python3-syspurpose
-+%endif
- 
- %description
- The tuned package contains a daemon that tunes system settings dynamically.
-diff --git a/tuned/utils/commands.py b/tuned/utils/commands.py
-index 8bb31a3..9a81baf 100644
---- a/tuned/utils/commands.py
-+++ b/tuned/utils/commands.py
-@@ -10,6 +10,11 @@ import procfs
- from subprocess import *
- from tuned.exceptions import TunedException
- import dmidecode
-+try:
-+	import syspurpose.files
-+	have_syspurpose = True
-+except:
-+	have_syspurpose = False
- 
- log = tuned.logs.get()
- 
-@@ -421,6 +426,23 @@ class commands:
- 								break
- 						else:
- 							match = False
-+					elif option == "syspurpose_role":
-+						if have_syspurpose:
-+							s = syspurpose.files.SyspurposeStore(
-+									syspurpose.files.USER_SYSPURPOSE,
-+									raise_on_error = True)
-+							role = ""
-+							try:
-+								s.read_file()
-+								role = s.contents["role"]
-+							except (IOError, OSError, KeyError) as e:
-+								if hasattr(e, "errno") and e.errno != errno.ENOENT:
-+									log.error("Failed to load the syspurpose file: %s" % e)
-+							if re.match(value, role, re.IGNORECASE) is None:
-+								match = False
-+						else:
-+							log.error("Failed to process 'syspurpose_role' in '%s', the syspurpose module is not available" % fname)
-+
- 				if match:
- 					# remove the ",.*" suffix
- 					r = re.compile(r",[^,]*$")
--- 
-2.17.1
-
diff --git a/SOURCES/tuned-2.10.0-add-support-for-bls.patch b/SOURCES/tuned-2.10.0-add-support-for-bls.patch
deleted file mode 100644
index ec8311b..0000000
--- a/SOURCES/tuned-2.10.0-add-support-for-bls.patch
+++ /dev/null
@@ -1,275 +0,0 @@
-From 731070a68e54e01015b520e2c19141a912923218 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com>
-Date: Sun, 9 Dec 2018 20:16:50 +0100
-Subject: [PATCH] Added support for Boot loader specification (BLS)
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves: rhbz#1576435
-
-Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
----
- 91-tuned.install                   | 31 ++++++++++++++++++++++
- Makefile                           |  6 ++++-
- tuned.spec                         | 19 ++++++++++++++
- tuned/consts.py                    |  3 +++
- tuned/plugins/plugin_bootloader.py | 41 +++++++++++++++++++++++++++---
- tuned/utils/commands.py            | 15 ++++++-----
- 6 files changed, 104 insertions(+), 11 deletions(-)
- create mode 100644 91-tuned.install
-
-diff --git a/91-tuned.install b/91-tuned.install
-new file mode 100644
-index 0000000..18d00d9
---- /dev/null
-+++ b/91-tuned.install
-@@ -0,0 +1,31 @@
-+#!/bin/bash
-+
-+COMMAND="$1"
-+KERNEL_VERSION="$2"
-+BOOT_DIR_ABS="$3"
-+KERNEL_IMAGE="$4"
-+
-+if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then
-+  exit 0
-+fi
-+
-+MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
-+
-+# with grub2 always /boot
-+BOOT_ROOT="/boot"
-+LOADER_ENTRIES="$BOOT_ROOT/loader/entries"
-+
-+[ -d "$LOADER_ENTRIES" ] || exit 0
-+
-+[ "$COMMAND" = "add" ] || exit 0
-+
-+pushd "$LOADER_ENTRIES"
-+for f in `basename "$MACHINE_ID"`-*.conf; do
-+  if [ -f "$f" -a "${f: -12}" != "-rescue.conf" ]; then
-+    grep -q '^\s*options\s\+.*\$tuned_params' "$f" || sed -i '/^\s*options\s\+/ s/\(.*\)/\1 \$tuned_params/' "$f"
-+    grep -q '^\s*initrd\s\+.*\$tuned_initrd' "$f" || sed -i '/^\s*initrd\s\+/ s/\(.*\)/\1 \$tuned_initrd/' "$f"
-+  fi
-+done
-+popd
-+
-+exit 0
-diff --git a/Makefile b/Makefile
-index 816fcb1..f61cd01 100644
---- a/Makefile
-+++ b/Makefile
-@@ -40,6 +40,7 @@ PYTHON_SITELIB = $(shell $(PYTHON) -c 'from distutils.sysconfig import get_pytho
- ifeq ($(PYTHON_SITELIB),)
- $(error Failed to determine python library directory)
- endif
-+KERNELINSTALLHOOKDIR = /usr/lib/kernel/install.d
- TUNED_PROFILESDIR = /usr/lib/tuned
- TUNED_RECOMMEND_DIR = $(TUNED_PROFILESDIR)/recommend.d
- TUNED_USER_RECOMMEND_DIR = $(SYSCONFDIR)/tuned/recommend.d
-@@ -59,7 +60,7 @@ release-cp: release-dir
- 
- 	cp -a tuned.py tuned.spec tuned.service tuned.tmpfiles Makefile tuned-adm.py \
- 		tuned-adm.bash dbus.conf recommend.conf tuned-main.conf 00_tuned \
--		bootcmdline modules.conf com.redhat.tuned.policy \
-+		91-tuned.install bootcmdline modules.conf com.redhat.tuned.policy \
- 		com.redhat.tuned.gui.policy tuned-gui.py tuned-gui.glade \
- 		tuned-gui.desktop $(VERSIONED_NAME)
- 	cp -a doc experiments libexec man profiles systemtap tuned contrib icons \
-@@ -180,6 +181,9 @@ install: install-dirs
- 	# grub template
- 	install -Dpm 0755 00_tuned $(DESTDIR)$(SYSCONFDIR)/grub.d/00_tuned
- 
-+	# kernel install hook
-+	install -Dpm 0755 91-tuned.install $(DESTDIR)$(KERNELINSTALLHOOKDIR)/91-tuned.install
-+
- 	# polkit configuration
- 	install -Dpm 0644 com.redhat.tuned.policy $(DESTDIR)$(DATADIR)/polkit-1/actions/com.redhat.tuned.policy
- 	install -Dpm 0644 com.redhat.tuned.gui.policy $(DESTDIR)$(DATADIR)/polkit-1/actions/com.redhat.tuned.gui.policy
-diff --git a/tuned.spec b/tuned.spec
-index 1ecf320..b7ee60d 100644
---- a/tuned.spec
-+++ b/tuned.spec
-@@ -278,6 +278,24 @@ if [ "$1" == 0 ]; then
-   if [ -r "%{_sysconfdir}/default/grub" ]; then
-     sed -i '/GRUB_CMDLINE_LINUX_DEFAULT="${GRUB_CMDLINE_LINUX_DEFAULT:+$GRUB_CMDLINE_LINUX_DEFAULT }\\$tuned_params"/d' %{_sysconfdir}/default/grub
-   fi
-+
-+# cleanup for Boot loader specification (BLS)
-+
-+# clear grubenv variables
-+  grub2-editenv - unset tuned_params tuned_initrd &>/dev/null || :
-+# unpatch BLS entries
-+  MACHINE_ID=`cat /etc/machine-id 2>/dev/null`
-+  if [ "$MACHINE_ID" ]
-+  then
-+    for f in /boot/loader/entries/$MACHINE_ID-*.conf
-+    do
-+      if [ -f "$f" -a "${f: -12}" != "-rescue.conf" ]
-+      then
-+        sed -i '/^\s*options\s\+.*\$tuned_params/ s/\s\+\$tuned_params\b//g' "$f" &>/dev/null || :
-+        sed -i '/^\s*initrd\s\+.*\$tuned_initrd/ s/\s\+\$tuned_initrd\b//g' "$f" &>/dev/null || :
-+      fi
-+    done
-+  fi
- fi
- 
- 
-@@ -374,6 +392,7 @@ fi
- %{_datadir}/tuned/grub2
- %{_datadir}/polkit-1/actions/com.redhat.tuned.policy
- %ghost %{_sysconfdir}/modprobe.d/kvm.rt.tuned.conf
-+%{_prefix}/lib/kernel/install.d/91-tuned.install
- 
- %files gtk
- %defattr(-,root,root,-)
-diff --git a/tuned/consts.py b/tuned/consts.py
-index ab87c70..de94059 100644
---- a/tuned/consts.py
-+++ b/tuned/consts.py
-@@ -37,6 +37,9 @@ BOOT_CMDLINE_TUNED_VAR = "TUNED_BOOT_CMDLINE"
- BOOT_CMDLINE_INITRD_ADD_VAR = "TUNED_BOOT_INITRD_ADD"
- BOOT_CMDLINE_FILE = "/etc/tuned/bootcmdline"
- PETITBOOT_DETECT_DIR = "/sys/firmware/opal"
-+MACHINE_ID_FILE = "/etc/machine-id"
-+KERNEL_UPDATE_HOOK_FILE = "/usr/lib/kernel/install.d/91-tuned.install"
-+BLS_ENTRIES_PATH = "/boot/loader/entries"
- 
- # modules plugin configuration
- MODULES_FILE = "/etc/modprobe.d/tuned.conf"
-diff --git a/tuned/plugins/plugin_bootloader.py b/tuned/plugins/plugin_bootloader.py
-index d88b62c..400b07e 100644
---- a/tuned/plugins/plugin_bootloader.py
-+++ b/tuned/plugins/plugin_bootloader.py
-@@ -94,7 +94,7 @@ class BootloaderPlugin(base.Plugin):
- 
- 	def _remove_grub2_tuning(self):
- 		if not self._grub2_cfg_file_names:
--			log.error("cannot find grub.cfg to patch, you need to regenerate it by hand using grub2-mkconfig")
-+			log.info("cannot find grub.cfg to patch")
- 			return
- 		self._patch_bootcmdline({consts.BOOT_CMDLINE_TUNED_VAR : "", consts.BOOT_CMDLINE_INITRD_ADD_VAR : ""})
- 		for f in self._grub2_cfg_file_names:
-@@ -107,6 +107,7 @@ class BootloaderPlugin(base.Plugin):
- 		if full_rollback:
- 			log.info("removing grub2 tuning previously added by Tuned")
- 			self._remove_grub2_tuning()
-+			self._update_grubenv({"tuned_params" : "", "tuned_initrd" : ""})
- 
- 	def _grub2_cfg_unpatch(self, grub2_cfg):
- 		log.debug("unpatching grub.cfg")
-@@ -138,7 +139,7 @@ class BootloaderPlugin(base.Plugin):
- 	def _grub2_default_env_patch(self):
- 		grub2_default_env = self._cmd.read_file(consts.GRUB2_DEFAULT_ENV_FILE)
- 		if len(grub2_default_env) <= 0:
--			log.error("error reading '%s'" % consts.GRUB2_DEFAULT_ENV_FILE)
-+			log.info("cannot read '%s'" % consts.GRUB2_DEFAULT_ENV_FILE)
- 			return False
- 
- 		d = {"GRUB_CMDLINE_LINUX_DEFAULT" : consts.GRUB2_TUNED_VAR, "GRUB_INITRD_OVERLAY" : consts.GRUB2_TUNED_INITRD_VAR}
-@@ -157,12 +158,12 @@ class BootloaderPlugin(base.Plugin):
- 	def _grub2_cfg_patch(self, d):
- 		log.debug("patching grub.cfg")
- 		if not self._grub2_cfg_file_names:
--			log.error("cannot find grub.cfg to patch, you need to regenerate it by hand by grub2-mkconfig")
-+			log.info("cannot find grub.cfg to patch")
- 			return False
- 		for f in self._grub2_cfg_file_names:
- 			grub2_cfg = self._cmd.read_file(f)
- 			if len(grub2_cfg) <= 0:
--				log.error("error patching %s, you need to regenerate it by hand by grub2-mkconfig" % f)
-+				log.info("cannot patch %s" % f)
- 				return False
- 			log.debug("adding boot command line parameters to '%s'" % f)
- 			grub2_cfg_new = grub2_cfg
-@@ -187,6 +188,37 @@ class BootloaderPlugin(base.Plugin):
- 		self._grub2_cfg_patch({consts.GRUB2_TUNED_VAR : self._cmdline_val, consts.GRUB2_TUNED_INITRD_VAR : self._initrd_val})
- 		self._patch_bootcmdline({consts.BOOT_CMDLINE_TUNED_VAR : self._cmdline_val, consts.BOOT_CMDLINE_INITRD_ADD_VAR : self._initrd_val})
- 
-+	def _has_bls(self):
-+		return os.path.exists(consts.BLS_ENTRIES_PATH)
-+
-+	def _update_grubenv(self, d):
-+		log.debug("updating grubenv, setting %s" % str(d));
-+		l = ["%s=%s" % (str(option), str(value)) for option, value in d.items()]
-+		(rc, out) = self._cmd.execute(["grub2-editenv", "-", "set"] + l)
-+		if rc != 0:
-+			log.warn("cannot update grubenv: '%s'" % out)
-+			return False;
-+		return True
-+
-+	def _bls_entries_patch_initial(self):
-+		machine_id = self._cmd.get_machine_id()
-+		if machine_id == "":
-+			return False
-+		log.debug("running kernel update hook '%s' to patch BLS entries" % consts.KERNEL_UPDATE_HOOK_FILE)
-+		(rc, out) = self._cmd.execute([consts.KERNEL_UPDATE_HOOK_FILE, "add"], env = {"KERNEL_INSTALL_MACHINE_ID" : machine_id})
-+		if rc != 0:
-+			log.warn("cannot patch BLS entries: '%s'" % out)
-+			return False
-+		return True
-+
-+	def _bls_update(self):
-+		log.debug("updating BLS")
-+		if self._has_bls() and \
-+			self._update_grubenv({"tuned_params" : self._cmdline_val, "tuned_initrd" : self._initrd_val}) and \
-+			self._bls_entries_patch_initial():
-+				return True
-+		return False
-+
- 	def _init_initrd_dst_img(self, name):
- 		if self._initrd_dst_img_val is None:
- 			self._initrd_dst_img_val = os.path.join(consts.BOOT_DIR, os.path.basename(name))
-@@ -307,4 +339,5 @@ class BootloaderPlugin(base.Plugin):
- 	def _instance_post_static(self, instance, enabling):
- 		if enabling and self.update_grub2_cfg:
- 			self._grub2_update()
-+			self._bls_update()
- 			self.update_grub2_cfg = False
-diff --git a/tuned/utils/commands.py b/tuned/utils/commands.py
-index 5692450..68d2ea5 100644
---- a/tuned/utils/commands.py
-+++ b/tuned/utils/commands.py
-@@ -25,7 +25,6 @@ log = tuned.logs.get()
- class commands:
- 
- 	def __init__(self, logging = True):
--		self._environment = None
- 		self._logging = logging
- 
- 	def _error(self, msg):
-@@ -208,21 +207,25 @@ class commands:
- 
- 		return self.write_to_file(f, data)
- 
-+	# returns machine ID or empty string "" in case of error
-+	def get_machine_id(self, no_error = True):
-+		return self.read_file(consts.MACHINE_ID_FILE, no_error).strip()
-+
- 	# "no_errors" can be list of return codes not treated as errors, if 0 is in no_errors, it means any error
- 	# returns (retcode, out), where retcode is exit code of the executed process or -errno if
- 	# OSError or IOError exception happened
--	def execute(self, args, shell = False, cwd = None, no_errors = [], return_err = False):
-+	def execute(self, args, shell = False, cwd = None, env = {}, no_errors = [], return_err = False):
- 		retcode = 0
--		if self._environment is None:
--			self._environment = os.environ.copy()
--			self._environment["LC_ALL"] = "C"
-+		_environment = os.environ.copy()
-+		_environment["LC_ALL"] = "C"
-+		_environment.update(env)
- 
- 		self._debug("Executing %s." % str(args))
- 		out = ""
- 		err_msg = None
- 		try:
- 			proc = Popen(args, stdout = PIPE, stderr = PIPE, \
--					env = self._environment, \
-+					env = _environment, \
- 					shell = shell, cwd = cwd, \
- 					close_fds = True, \
- 					universal_newlines = True)
--- 
-2.17.2
-
diff --git a/SOURCES/tuned-2.10.0-disable-ksm-once.patch b/SOURCES/tuned-2.10.0-disable-ksm-once.patch
deleted file mode 100644
index a35883d..0000000
--- a/SOURCES/tuned-2.10.0-disable-ksm-once.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-diff --git a/profiles/cpu-partitioning/script.sh b/profiles/cpu-partitioning/script.sh
-index 0e94d3a..efe9bcb 100755
---- a/profiles/cpu-partitioning/script.sh
-+++ b/profiles/cpu-partitioning/script.sh
-@@ -54,8 +54,8 @@ stop() {
-     then
-         sed -i '/^IRQBALANCE_BANNED_CPUS=/d' /etc/sysconfig/irqbalance
-         teardown_kvm_mod_low_latency
-+        enable_ksm
-     fi
--    enable_ksm
-     enable_balance_domains
-     return "$?"
- }
-diff --git a/profiles/functions b/profiles/functions
-index 1ed0120..aab608a 100644
---- a/profiles/functions
-+++ b/profiles/functions
-@@ -531,35 +531,30 @@ setup_kvm_mod_low_latency()
- 
- KSM_SERVICES="ksm ksmtuned"
- KSM_RUN_PATH=/sys/kernel/mm/ksm/run
-+KSM_MASK_FILE="${STORAGE_PERSISTENT}/ksm-masked"
- 
- disable_ksm()
- {
--	for s in $KSM_SERVICES; do
--		if systemctl is-enabled -q $s; then
--			systemctl -q disable $s
-+	if [ ! -f $KSM_MASK_FILE ]; then
-+		# Always create $KSM_MASK_FILE, since we don't want to
-+		# run any systemctl commands during boot
-+		if ! touch $KSM_MASK_FILE; then
-+			die "failed to create $KSM_MASK_FILE"
- 		fi
--
--		if systemctl is-active -q $s; then
--			systemctl -q stop $s
--		fi
--	done
--
--	if [ -f $KSM_RUN_PATH ]; then
-+		systemctl --now --quiet mask $KSM_SERVICES
- 		# Unmerge all shared pages
--		echo 2 > $KSM_RUN_PATH
-+		test -f $KSM_RUN_PATH && echo 2 > $KSM_RUN_PATH
- 	fi
- }
- 
-+# Should only be called when full_rollback == true
- enable_ksm()
- {
--	for s in $KSM_SERVICES; do
--		systemctl -q preset $s
--
--		# Only start the service if it's enabled by defaut
--		if systemctl is-enabled -q $s; then
--			systemctl start $s
-+	if [ -f $KSM_MASK_FILE ]; then
-+		if systemctl --quiet unmask $KSM_SERVICES; then
-+			rm -f $KSM_MASK_FILE
- 		fi
--	done
-+	fi
- }
- 
- die() {
-diff --git a/profiles/realtime-virtual-host/script.sh b/profiles/realtime-virtual-host/script.sh
-index a9366cb..469ee2a 100755
---- a/profiles/realtime-virtual-host/script.sh
-+++ b/profiles/realtime-virtual-host/script.sh
-@@ -93,8 +93,10 @@ start() {
- }
- 
- stop() {
--    [ "$1" = "full_rollback" ] && teardown_kvm_mod_low_latency
--    enable_ksm
-+    if [ "$1" = "full_rollback" ]; then
-+        teardown_kvm_mod_low_latency
-+        enable_ksm
-+    fi
-     systemctl stop rt-entsk
-     return "$?"
- }
diff --git a/SOURCES/tuned-2.10.0-makefile-full-python-path.patch b/SOURCES/tuned-2.10.0-makefile-full-python-path.patch
deleted file mode 100644
index 39b3f4b..0000000
--- a/SOURCES/tuned-2.10.0-makefile-full-python-path.patch
+++ /dev/null
@@ -1,18 +0,0 @@
---- a/Makefile
-+++ b/Makefile
-@@ -30,12 +30,12 @@ VERSIONED_NAME = $(NAME)-$(VERSION)$(GIT_PSUFFIX)
- SYSCONFDIR = /etc
- DATADIR = /usr/share
- DOCDIR = $(DATADIR)/doc/$(NAME)
--PYTHON = python3
-+PYTHON = /usr/bin/python3
- PYLINT = pylint-3
- ifeq ($(PYTHON),python2)
- PYLINT = pylint-2
- endif
--SHEBANG_REWRITE_REGEX= '1s/^(\#!\/usr\/bin\/)\<python\>/\1$(PYTHON)/'
-+SHEBANG_REWRITE_REGEX= '1s|^\#!/usr/bin/\<python\>|\#!$(PYTHON)|'
- PYTHON_SITELIB = $(shell $(PYTHON) -c 'from distutils.sysconfig import get_python_lib; print(get_python_lib());')
- ifeq ($(PYTHON_SITELIB),)
- $(error Failed to determine python library directory)
-
diff --git a/SOURCES/tuned-2.10.0-mssql-tuning.patch b/SOURCES/tuned-2.10.0-mssql-tuning.patch
deleted file mode 100644
index df200c3..0000000
--- a/SOURCES/tuned-2.10.0-mssql-tuning.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 26db89de18efad1b453618ea8156422d26e0c85f Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com>
-Date: Tue, 8 Jan 2019 15:00:33 +0100
-Subject: [PATCH] mssql: updated tuning
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Added vm plugin option 'transparent_hugepage.defrag'.
-
-Resolves: rhbz#1660178
-
-Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
----
- profiles/mssql/tuned.conf  |  9 ++++++++-
- tuned/plugins/plugin_vm.py | 32 +++++++++++++++++++++++++++-----
- 2 files changed, 35 insertions(+), 6 deletions(-)
-
-diff --git a/profiles/mssql/tuned.conf b/profiles/mssql/tuned.conf
-index 2491717..35e208a 100644
---- a/profiles/mssql/tuned.conf
-+++ b/profiles/mssql/tuned.conf
-@@ -6,5 +6,12 @@
- summary=Optimize for MS SQL Server
- include=throughput-performance
- 
-+[vm]
-+transparent_hugepage.defrag=always
-+
- [sysctl]
--vm.max_map_count=262144
-+vm.max_map_count=800000
-+kernel.numa_balancing=0
-+kernel.sched_latency_ns=60000000
-+kernel.sched_min_granularity_ns=15000000
-+kernel.sched_wakeup_granularity_ns=2000000
-diff --git a/tuned/plugins/plugin_vm.py b/tuned/plugins/plugin_vm.py
-index be570e2..9021ac3 100644
---- a/tuned/plugins/plugin_vm.py
-+++ b/tuned/plugins/plugin_vm.py
-@@ -20,6 +20,7 @@ class VMPlugin(base.Plugin):
- 		return {
- 			"transparent_hugepages" : None,
- 			"transparent_hugepage" : None,
-+			"transparent_hugepage.defrag" : None,
- 		}
- 
- 	def _instance_init(self, instance):
-@@ -30,10 +31,11 @@ class VMPlugin(base.Plugin):
- 		pass
- 
- 	@classmethod
--	def _thp_file(self):
--		path = "/sys/kernel/mm/transparent_hugepage/enabled"
-+	def _thp_path(self):
-+		path = "/sys/kernel/mm/transparent_hugepage"
- 		if not os.path.exists(path):
--			path =  "/sys/kernel/mm/redhat_transparent_hugepage/enabled"
-+			# RHEL-6 support
-+			path =  "/sys/kernel/mm/redhat_transparent_hugepage"
- 		return path
- 
- 	@command_set("transparent_hugepages")
-@@ -49,7 +51,7 @@ class VMPlugin(base.Plugin):
- 				log.info("transparent_hugepage is already set in kernel boot cmdline, ingoring value from profile")
- 			return None
- 
--		sys_file = self._thp_file()
-+		sys_file = os.path.join(self._thp_path(), "enabled")
- 		if os.path.exists(sys_file):
- 			if not sim:
- 				cmd.write_to_file(sys_file, value)
-@@ -66,7 +68,7 @@ class VMPlugin(base.Plugin):
- 
- 	@command_get("transparent_hugepages")
- 	def _get_transparent_hugepages(self):
--		sys_file = self._thp_file()
-+		sys_file = os.path.join(self._thp_path(), "enabled")
- 		if os.path.exists(sys_file):
- 			return cmd.get_active_option(cmd.read_file(sys_file))
- 		else:
-@@ -76,3 +78,23 @@ class VMPlugin(base.Plugin):
- 	@command_get("transparent_hugepage")
- 	def _get_transparent_hugepage(self):
- 		return self._get_transparent_hugepages()
-+
-+	@command_set("transparent_hugepage.defrag")
-+	def _set_transparent_hugepage_defrag(self, value, sim):
-+		sys_file = os.path.join(self._thp_path(), "defrag")
-+		if os.path.exists(sys_file):
-+			if not sim:
-+				cmd.write_to_file(sys_file, value)
-+			return value
-+		else:
-+			if not sim:
-+				log.warn("Option 'transparent_hugepage.defrag' is not supported on current hardware.")
-+			return None
-+
-+	@command_get("transparent_hugepage.defrag")
-+	def _get_transparent_hugepage_defrag(self):
-+		sys_file = os.path.join(self._thp_path(), "defrag")
-+		if os.path.exists(sys_file):
-+			return cmd.get_active_option(cmd.read_file(sys_file))
-+		else:
-+			return None
--- 
-2.20.1
-
diff --git a/SOURCES/tuned-2.10.0-python-3.7-fix.patch b/SOURCES/tuned-2.10.0-python-3.7-fix.patch
deleted file mode 100644
index 9c90c67..0000000
--- a/SOURCES/tuned-2.10.0-python-3.7-fix.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From f19b7c5713acb76a200811f6531acf2791505cac Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com>
-Date: Wed, 4 Jul 2018 23:27:38 +0200
-Subject: [PATCH] Fixed compatibility with python-3.7
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In python-3.7 async is a keyword, so it cannot be redefined.
-
-Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
----
- tuned-adm.py         | 4 ++--
- tuned/admin/admin.py | 4 ++--
- 2 files changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/tuned-adm.py b/tuned-adm.py
-index ea85c54..1b9623d 100755
---- a/tuned-adm.py
-+++ b/tuned-adm.py
-@@ -98,7 +98,7 @@ if __name__ == "__main__":
- 
- 	options = vars(args)
- 	debug = options.pop("debug")
--	async = options.pop("async")
-+	asynco = options.pop("async")
- 	timeout = options.pop("timeout")
- 	action_name = options.pop("action")
- 	log_level = options.pop("loglevel")
-@@ -107,7 +107,7 @@ if __name__ == "__main__":
- 	dbus = config.get_bool(consts.CFG_DAEMON, consts.CFG_DEF_DAEMON)
- 
- 	try:
--		admin = tuned.admin.Admin(dbus, debug, async, timeout, log_level)
-+		admin = tuned.admin.Admin(dbus, debug, asynco, timeout, log_level)
- 
- 		result = admin.action(action_name, **options)
- 	except:
-diff --git a/tuned/admin/admin.py b/tuned/admin/admin.py
-index 728af32..3f84413 100644
---- a/tuned/admin/admin.py
-+++ b/tuned/admin/admin.py
-@@ -14,12 +14,12 @@ import threading
- import logging
- 
- class Admin(object):
--	def __init__(self, dbus = True, debug = False, async = False,
-+	def __init__(self, dbus = True, debug = False, asynco = False,
- 			timeout = consts.ADMIN_TIMEOUT,
- 			log_level = logging.ERROR):
- 		self._dbus = dbus
- 		self._debug = debug
--		self._async = async
-+		self._async = asynco
- 		self._timeout = timeout
- 		self._cmd = commands(debug)
- 		self._profiles_locator = profiles_locator(consts.LOAD_DIRECTORIES)
--- 
-2.14.4
-
diff --git a/SOURCES/tuned-2.10.0-realtime-virtual-enable-rt-entsk.patch b/SOURCES/tuned-2.10.0-realtime-virtual-enable-rt-entsk.patch
deleted file mode 100644
index e464f0f..0000000
--- a/SOURCES/tuned-2.10.0-realtime-virtual-enable-rt-entsk.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From 837c6bd12a5eedc3fbf46291bf1040e724786efd Mon Sep 17 00:00:00 2001
-From: Marcelo Tosatti <mtosatti@redhat.com>
-Date: Fri, 31 Aug 2018 13:27:12 +0200
-Subject: [PATCH] start/stop rt-entsk daemon on initialization/shutdown
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The rt-entsk application, part of newer rt-setup packages,
-worksaround a latency issue with static key
-IPI's. What it does it:
-
-/*
- * Open a socket, and enable timestamping on it.
- *
- * This is to avoid Chrony from changing timestamping
- * user count from 0->1 and vice-versa, causing
- * static key enable/disable IPIs.
- *
- */
-
-Start/stop the systemctl service from the realtime-virtual-host
-and realtime-virtual-guest profiles.
-
-Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
----
- profiles/realtime-virtual-guest/script.sh  | 19 +++++++++++++++++++
- profiles/realtime-virtual-guest/tuned.conf |  3 +++
- profiles/realtime-virtual-host/script.sh   |  2 ++
- 3 files changed, 24 insertions(+)
- create mode 100755 profiles/realtime-virtual-guest/script.sh
-
-diff --git a/profiles/realtime-virtual-guest/script.sh b/profiles/realtime-virtual-guest/script.sh
-new file mode 100755
-index 0000000..33cb730
---- /dev/null
-+++ b/profiles/realtime-virtual-guest/script.sh
-@@ -0,0 +1,19 @@
-+#!/bin/sh
-+
-+. /usr/lib/tuned/functions
-+
-+start() {
-+    systemctl start rt-entsk
-+    return "$?"
-+}
-+
-+stop() {
-+    systemctl stop rt-entsk
-+    return "$?"
-+}
-+
-+verify() {
-+    return "$?"
-+}
-+
-+process $@
-diff --git a/profiles/realtime-virtual-guest/tuned.conf b/profiles/realtime-virtual-guest/tuned.conf
-index fb2bc42..8e1f67e 100644
---- a/profiles/realtime-virtual-guest/tuned.conf
-+++ b/profiles/realtime-virtual-guest/tuned.conf
-@@ -36,5 +36,8 @@ group.ktimersoftd=0:f:3:*:ktimersoftd.*
- 
- ps_blacklist=ksoftirqd.*;rcuc.*;rcub.*;ktimersoftd.*
- 
-+[script]
-+script=${i:PROFILE_DIR}/script.sh
-+
- [bootloader]
- cmdline_rvg=+nohz=on nohz_full=${isolated_cores} rcu_nocbs=${isolated_cores}
-diff --git a/profiles/realtime-virtual-host/script.sh b/profiles/realtime-virtual-host/script.sh
-index 515d254..a9366cb 100755
---- a/profiles/realtime-virtual-host/script.sh
-+++ b/profiles/realtime-virtual-host/script.sh
-@@ -87,6 +87,7 @@ start() {
-     if [ -f $CACHE_VALUE_FILE ]; then
-         echo `cat $CACHE_VALUE_FILE` > $KVM_LAPIC_FILE
-     fi
-+    systemctl start rt-entsk
- 
-     return 0
- }
-@@ -94,6 +95,7 @@ start() {
- stop() {
-     [ "$1" = "full_rollback" ] && teardown_kvm_mod_low_latency
-     enable_ksm
-+    systemctl stop rt-entsk
-     return "$?"
- }
- 
--- 
-2.14.4
-
diff --git a/SOURCES/tuned-2.10.0-s390x-bls-workaround.patch b/SOURCES/tuned-2.10.0-s390x-bls-workaround.patch
deleted file mode 100644
index e780e94..0000000
--- a/SOURCES/tuned-2.10.0-s390x-bls-workaround.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 41b38ab6e7a411e609776eec544451f3de76e523 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com>
-Date: Mon, 10 Dec 2018 17:49:54 +0100
-Subject: [PATCH] Added workaround for zipl (s390x) not supporting multiple
- initrds
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This workaround can be removed once implemented upstream, ticket:
-https://github.com/ibm-s390-tools/s390-tools/issues/49
-
-RHEL bugzilla:
-rhbz#1576435
-
-Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
----
- 91-tuned.install => 92-tuned.install | 15 ++++++++++++---
- Makefile                             |  4 ++--
- tuned.spec                           |  2 +-
- tuned/consts.py                      |  2 +-
- 4 files changed, 16 insertions(+), 7 deletions(-)
- rename 91-tuned.install => 92-tuned.install (58%)
-
-diff --git a/91-tuned.install b/92-tuned.install
-similarity index 58%
-rename from 91-tuned.install
-rename to 92-tuned.install
-index 18d00d9..00eefc7 100644
---- a/91-tuned.install
-+++ b/92-tuned.install
-@@ -19,13 +19,22 @@ LOADER_ENTRIES="$BOOT_ROOT/loader/entries"
- 
- [ "$COMMAND" = "add" ] || exit 0
- 
--pushd "$LOADER_ENTRIES"
-+# Workaround for rhbz#1657858
-+ARCH=`uname -m`
-+[ "${ARCH:0:4}" = "s390" ]
-+HANDLE_INITRD="$?"
-+
-+pushd "$LOADER_ENTRIES" &> /dev/null
- for f in `basename "$MACHINE_ID"`-*.conf; do
-   if [ -f "$f" -a "${f: -12}" != "-rescue.conf" ]; then
-     grep -q '^\s*options\s\+.*\$tuned_params' "$f" || sed -i '/^\s*options\s\+/ s/\(.*\)/\1 \$tuned_params/' "$f"
--    grep -q '^\s*initrd\s\+.*\$tuned_initrd' "$f" || sed -i '/^\s*initrd\s\+/ s/\(.*\)/\1 \$tuned_initrd/' "$f"
-+    if [ "$HANDLE_INITRD" = "1" ]; then
-+      grep -q '^\s*initrd\s\+.*\$tuned_initrd' "$f" || sed -i '/^\s*initrd\s\+/ s/\(.*\)/\1 \$tuned_initrd/' "$f"
-+    else
-+      sed -i '/^\s*initrd\s\+.*\$tuned_initrd/ s/\s\+\$tuned_initrd\b//g' "$f"
-+    fi
-   fi
- done
--popd
-+popd &> /dev/null
- 
- exit 0
-diff --git a/Makefile b/Makefile
-index f61cd01..36e22ff 100644
---- a/Makefile
-+++ b/Makefile
-@@ -60,7 +60,7 @@ release-cp: release-dir
- 
- 	cp -a tuned.py tuned.spec tuned.service tuned.tmpfiles Makefile tuned-adm.py \
- 		tuned-adm.bash dbus.conf recommend.conf tuned-main.conf 00_tuned \
--		91-tuned.install bootcmdline modules.conf com.redhat.tuned.policy \
-+		92-tuned.install bootcmdline modules.conf com.redhat.tuned.policy \
- 		com.redhat.tuned.gui.policy tuned-gui.py tuned-gui.glade \
- 		tuned-gui.desktop $(VERSIONED_NAME)
- 	cp -a doc experiments libexec man profiles systemtap tuned contrib icons \
-@@ -182,7 +182,7 @@ install: install-dirs
- 	install -Dpm 0755 00_tuned $(DESTDIR)$(SYSCONFDIR)/grub.d/00_tuned
- 
- 	# kernel install hook
--	install -Dpm 0755 91-tuned.install $(DESTDIR)$(KERNELINSTALLHOOKDIR)/91-tuned.install
-+	install -Dpm 0755 92-tuned.install $(DESTDIR)$(KERNELINSTALLHOOKDIR)/92-tuned.install
- 
- 	# polkit configuration
- 	install -Dpm 0644 com.redhat.tuned.policy $(DESTDIR)$(DATADIR)/polkit-1/actions/com.redhat.tuned.policy
-diff --git a/tuned.spec b/tuned.spec
-index 300c8aa..6ac575e 100644
---- a/tuned.spec
-+++ b/tuned.spec
-@@ -392,7 +392,7 @@ fi
- %{_datadir}/tuned/grub2
- %{_datadir}/polkit-1/actions/com.redhat.tuned.policy
- %ghost %{_sysconfdir}/modprobe.d/kvm.rt.tuned.conf
--%{_prefix}/lib/kernel/install.d/91-tuned.install
-+%{_prefix}/lib/kernel/install.d/92-tuned.install
- 
- %files gtk
- %defattr(-,root,root,-)
-diff --git a/tuned/consts.py b/tuned/consts.py
-index de94059..39f9209 100644
---- a/tuned/consts.py
-+++ b/tuned/consts.py
-@@ -38,7 +38,7 @@ BOOT_CMDLINE_INITRD_ADD_VAR = "TUNED_BOOT_INITRD_ADD"
- BOOT_CMDLINE_FILE = "/etc/tuned/bootcmdline"
- PETITBOOT_DETECT_DIR = "/sys/firmware/opal"
- MACHINE_ID_FILE = "/etc/machine-id"
--KERNEL_UPDATE_HOOK_FILE = "/usr/lib/kernel/install.d/91-tuned.install"
-+KERNEL_UPDATE_HOOK_FILE = "/usr/lib/kernel/install.d/92-tuned.install"
- BLS_ENTRIES_PATH = "/boot/loader/entries"
- 
- # modules plugin configuration
--- 
-2.17.2
-
diff --git a/SOURCES/tuned-2.10.0-update-kvm-modprobe-file.patch b/SOURCES/tuned-2.10.0-update-kvm-modprobe-file.patch
deleted file mode 100644
index d4d4886..0000000
--- a/SOURCES/tuned-2.10.0-update-kvm-modprobe-file.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-From c4a0aef63df41a79e96c1276ac732ecde8d58d86 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com>
-Date: Thu, 22 Nov 2018 17:38:12 +0100
-Subject: [PATCH] functions: reworked setup_kvm_mod_low_latency to count with
- kernel changes
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-It updates the KVM modprobe file if its content differs from what's
-supported on the current system. It may look a bit over-engineered, but
-it's done this way to lower the possibility of race condition.
-
-Resolves: rhbz#1649408
-
-Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
----
- profiles/functions | 35 +++++++++++++++++++----------------
- 1 file changed, 19 insertions(+), 16 deletions(-)
-
-diff --git a/profiles/functions b/profiles/functions
-index 919409c..aab608a 100644
---- a/profiles/functions
-+++ b/profiles/functions
-@@ -503,26 +503,29 @@ eee_set_normal_fsb() {
- 
- kvm_modprobe_file=/etc/modprobe.d/kvm.rt.tuned.conf
- 
--setup_kvm_mod_low_latency()
-+teardown_kvm_mod_low_latency()
- {
--	if [ -f $kvm_modprobe_file ]; then
--		return
--	fi
--
--	modinfo -p kvm | grep -q kvmclock_periodic_sync
--	if [ "$?" -eq 0 ]; then
--		echo "options kvm kvmclock_periodic_sync=0" > $kvm_modprobe_file
--	fi
--
--	modinfo -p kvm_intel | grep -q ple_gap
--	if [ "$?" -eq 0 ]; then
--		echo "options kvm_intel ple_gap=0" >> $kvm_modprobe_file
--	fi
-+	rm -f $kvm_modprobe_file
- }
- 
--teardown_kvm_mod_low_latency()
-+setup_kvm_mod_low_latency()
- {
--	rm -f $kvm_modprobe_file
-+	local HAS_KPS=""
-+	local HAS_PLE_GAP=""
-+	local WANTS_KPS=""
-+	local WANTS_PLE_GAP=""
-+
-+	modinfo -p kvm | grep -q kvmclock_periodic_sync && HAS_KPS=1
-+	modinfo -p kvm_intel | grep -q ple_gap && HAS_PLE_GAP=1
-+	grep -qs kvmclock_periodic_sync "$kvm_modprobe_file" && WANTS_KPS=1
-+	grep -qs ple_gap "$kvm_modprobe_file" && WANTS_PLE_GAP=1
-+
-+	if [ "$HAS_KPS" != "$WANTS_KPS" -o "$HAS_PLE_GAP" != "$WANTS_PLE_GAP" ]; then
-+		teardown_kvm_mod_low_latency
-+		[ "$HAS_KPS" ] && echo "options kvm kvmclock_periodic_sync=0" > $kvm_modprobe_file
-+		[ "$HAS_PLE_GAP" ] && echo "options kvm_intel ple_gap=0" >> $kvm_modprobe_file
-+	fi
-+	return 0
- }
- 
- #
--- 
-2.14.5
-
diff --git a/SOURCES/tuned-2.10.0-use-online-cpus.patch b/SOURCES/tuned-2.10.0-use-online-cpus.patch
deleted file mode 100644
index 8cc34fd..0000000
--- a/SOURCES/tuned-2.10.0-use-online-cpus.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-diff --git a/profiles/cpu-partitioning/tuned.conf b/profiles/cpu-partitioning/tuned.conf
-index 3c52215..1821b74 100644
---- a/profiles/cpu-partitioning/tuned.conf
-+++ b/profiles/cpu-partitioning/tuned.conf
-@@ -19,13 +19,13 @@ tmpdir=${f:strip:${f:exec:/usr/bin/mktemp:-d}}
- isolated_cores_expanded=${f:cpulist_unpack:${isolated_cores}}
- isolated_cpumask=${f:cpulist2hex:${isolated_cores_expanded}}
- not_isolated_cores_expanded=${f:cpulist_invert:${isolated_cores_expanded}}
--isolated_cores_present_expanded=${f:cpulist_present:${isolated_cores}}
--not_isolated_cores_present_expanded=${f:cpulist_present:${not_isolated_cores_expanded}}
-+isolated_cores_online_expanded=${f:cpulist_online:${isolated_cores}}
-+not_isolated_cores_online_expanded=${f:cpulist_online:${not_isolated_cores_expanded}}
- not_isolated_cpumask=${f:cpulist2hex:${not_isolated_cores_expanded}}
- no_balance_cores_expanded=${f:cpulist_unpack:${no_balance_cores}}
- 
--# Fail if isolated_cores contains CPUs which are not present
--assert2=${f:assertion:isolated_cores contains present CPU(s):${isolated_cores_expanded}:${isolated_cores_present_expanded}}
-+# Fail if isolated_cores contains CPUs which are not online
-+assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}}
- 
- [sysctl]
- kernel.hung_task_timeout_secs = 600
-diff --git a/profiles/realtime-virtual-guest/tuned.conf b/profiles/realtime-virtual-guest/tuned.conf
-index b90e76f..fb2bc42 100644
---- a/profiles/realtime-virtual-guest/tuned.conf
-+++ b/profiles/realtime-virtual-guest/tuned.conf
-@@ -15,10 +15,10 @@ isolated_cores_assert_check = \\${isolated_cores}
- assert1=${f:assertion_non_equal:isolated_cores are set:${isolated_cores}:${isolated_cores_assert_check}}
- 
- isolated_cores_expanded=${f:cpulist_unpack:${isolated_cores}}
--isolated_cores_present_expanded=${f:cpulist_present:${isolated_cores}}
-+isolated_cores_online_expanded=${f:cpulist_online:${isolated_cores}}
- 
--# Fail if isolated_cores contains CPUs which are not present
--assert2=${f:assertion:isolated_cores contains present CPU(s):${isolated_cores_expanded}:${isolated_cores_present_expanded}}
-+# Fail if isolated_cores contains CPUs which are not online
-+assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}}
- 
- [scheduler]
- # group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex
-diff --git a/profiles/realtime-virtual-host/tuned.conf b/profiles/realtime-virtual-host/tuned.conf
-index 0346fff..5e0ff1f 100644
---- a/profiles/realtime-virtual-host/tuned.conf
-+++ b/profiles/realtime-virtual-host/tuned.conf
-@@ -20,10 +20,10 @@ isolated_cores_assert_check = \\${isolated_cores}
- assert1=${f:assertion_non_equal:isolated_cores are set:${isolated_cores}:${isolated_cores_assert_check}}
- 
- isolated_cores_expanded=${f:cpulist_unpack:${isolated_cores}}
--isolated_cores_present_expanded=${f:cpulist_present:${isolated_cores}}
-+isolated_cores_online_expanded=${f:cpulist_online:${isolated_cores}}
- 
--# Fail if isolated_cores contains CPUs which are not present
--assert2=${f:assertion:isolated_cores contains present CPU(s):${isolated_cores_expanded}:${isolated_cores_present_expanded}}
-+# Fail if isolated_cores contains CPUs which are not online
-+assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}}
- 
- [scheduler]
- # group.group_name=rule_priority:scheduler_policy:scheduler_priority:core_affinity_in_hex:process_name_regex
-diff --git a/profiles/realtime/tuned.conf b/profiles/realtime/tuned.conf
-index b2273cf..c595e67 100644
---- a/profiles/realtime/tuned.conf
-+++ b/profiles/realtime/tuned.conf
-@@ -18,10 +18,10 @@ assert1=${f:assertion_non_equal:isolated_cores are set:${isolated_cores}:${isola
- # Non-isolated cores cpumask including offline cores
- not_isolated_cpumask = ${f:cpulist2hex_invert:${isolated_cores}}
- isolated_cores_expanded=${f:cpulist_unpack:${isolated_cores}}
--isolated_cores_present_expanded=${f:cpulist_present:${isolated_cores}}
-+isolated_cores_online_expanded=${f:cpulist_online:${isolated_cores}}
- 
--# Fail if isolated_cores contains CPUs which are not present
--assert2=${f:assertion:isolated_cores contains present CPU(s):${isolated_cores_expanded}:${isolated_cores_present_expanded}}
-+# Fail if isolated_cores contains CPUs which are not online
-+assert2=${f:assertion:isolated_cores contains online CPU(s):${isolated_cores_expanded}:${isolated_cores_online_expanded}}
- 
- [sysctl]
- kernel.hung_task_timeout_secs = 600
-diff --git a/tuned/profiles/functions/function_cpulist_invert.py b/tuned/profiles/functions/function_cpulist_invert.py
-index 375eb67..2aff3c9 100644
---- a/tuned/profiles/functions/function_cpulist_invert.py
-+++ b/tuned/profiles/functions/function_cpulist_invert.py
-@@ -8,7 +8,7 @@ log = tuned.logs.get()
- class cpulist_invert(base.Function):
- 	"""
- 	Inverts list of CPUs (makes its complement). For the complement it
--	gets number of present CPUs from the /sys/devices/system/cpu/present,
-+	gets number of present CPUs from the /sys/devices/system/cpu/online,
- 	e.g. system with 4 CPUs (0-3), the inversion of list "0,2,3" will be
- 	"1"
- 	"""
-diff --git a/tuned/utils/commands.py b/tuned/utils/commands.py
-index 8b7df57..41d6d99 100644
---- a/tuned/utils/commands.py
-+++ b/tuned/utils/commands.py
-@@ -363,8 +363,8 @@ class commands:
- 	# Inverts CPU list (i.e. makes its complement)
- 	def cpulist_invert(self, l):
- 		cpus = self.cpulist_unpack(l)
--		present = self.cpulist_unpack(self.read_file("/sys/devices/system/cpu/present"))
--		return list(set(present) - set(cpus))
-+		online = self.cpulist_unpack(self.read_file("/sys/devices/system/cpu/online"))
-+		return list(set(online) - set(cpus))
- 
- 	# Converts CPU list to hexadecimal CPU mask
- 	def cpulist2hex(self, l):
diff --git a/SOURCES/tuned-2.12-latency-as-cstate.patch b/SOURCES/tuned-2.12-latency-as-cstate.patch
new file mode 100644
index 0000000..69bcb0d
--- /dev/null
+++ b/SOURCES/tuned-2.12-latency-as-cstate.patch
@@ -0,0 +1,131 @@
+diff --git a/profiles/latency-performance/tuned.conf b/profiles/latency-performance/tuned.conf
+index 054c554..4cd69a1 100644
+--- a/profiles/latency-performance/tuned.conf
++++ b/profiles/latency-performance/tuned.conf
+@@ -6,7 +6,7 @@
+ summary=Optimize for deterministic performance at the cost of increased power consumption
+ 
+ [cpu]
+-force_latency=1
++force_latency=cstate.id:1|1
+ governor=performance
+ energy_perf_bias=performance
+ min_perf_pct=100
+diff --git a/profiles/sap-hana/tuned.conf b/profiles/sap-hana/tuned.conf
+index 9afac82..d74250b 100644
+--- a/profiles/sap-hana/tuned.conf
++++ b/profiles/sap-hana/tuned.conf
+@@ -7,7 +7,7 @@ summary=Optimize for SAP HANA
+ include=throughput-performance
+ 
+ [cpu]
+-force_latency=70
++force_latency=cstate.id:3|70
+ 
+ [vm]
+ transparent_hugepages=never
+diff --git a/profiles/virtual-host/tuned.conf b/profiles/virtual-host/tuned.conf
+index ca493d6..8acb92d 100644
+--- a/profiles/virtual-host/tuned.conf
++++ b/profiles/virtual-host/tuned.conf
+@@ -18,4 +18,4 @@ kernel.sched_migration_cost_ns = 5000000
+ 
+ [cpu]
+ # Setting C3 state sleep mode/power savings
+-force_latency=70
++force_latency=cstate.id:3|70
+diff --git a/tuned/plugins/plugin_cpu.py b/tuned/plugins/plugin_cpu.py
+index 77e9448..04c7b19 100644
+--- a/tuned/plugins/plugin_cpu.py
++++ b/tuned/plugins/plugin_cpu.py
+@@ -12,8 +12,7 @@ import procfs
+ 
+ log = tuned.logs.get()
+ 
+-# TODO: force_latency -> command
+-#       intel_pstate
++cpuidle_states_path = "/sys/devices/system/cpu/cpu0/cpuidle"
+ 
+ class CPULatencyPlugin(base.Plugin):
+ 	"""
+@@ -210,13 +209,74 @@ class CPULatencyPlugin(base.Plugin):
+ 	def _instance_unapply_dynamic(self, instance, device):
+ 		pass
+ 
++	def _str2int(self, s):
++		try:
++			return int(s)
++		except (ValueError, TypeError):
++			return None
++
++	def _read_cstates_latency(self):
++		self.cstates_latency = {}
++		for d in os.listdir(cpuidle_states_path):
++			cstate_path = cpuidle_states_path + "/%s/" % d
++			name = self._cmd.read_file(cstate_path + "name", err_ret = None, no_error = True)
++			latency = self._cmd.read_file(cstate_path + "latency", err_ret = None, no_error = True)
++			if name is not None and latency is not None:
++				latency = self._str2int(latency)
++				if latency is not None:
++					self.cstates_latency[name.strip()] = latency
++
++	def _get_latency_by_cstate_name(self, name):
++		log.debug("getting latency for cstate with name '%s'" % name)
++		if self.cstates_latency is None:
++			log.debug("reading cstates latency table")
++			self._read_cstates_latency()
++		latency = self.cstates_latency.get(name, None)
++		log.debug("cstate name mapped to latency: %s" % str(latency))
++		return latency
++
++	def _get_latency_by_cstate_id(self, lid):
++		log.debug("getting latency for cstate with ID '%s'" % str(lid))
++		lid = self._str2int(lid)
++		if lid is None:
++			log.debug("cstate ID is invalid")
++			return None
++		latency_path = cpuidle_states_path + "/%s/latency" % ("state%d" % lid)
++		latency = self._str2int(self._cmd.read_file(latency_path, err_ret = None, no_error = True))
++		log.debug("cstate ID mapped to latency: %s" % str(latency))
++		return latency
++
++	def _parse_latency(self, latency):
++		self.cstates_latency = None
++		latencies = str(latency).split("|")
++		log.debug("parsing latency")
++		for latency in latencies:
++			try:
++				latency = int(latency)
++				log.debug("parsed directly specified latency value: %d" % latency)
++			except ValueError:
++				if latency[0:10] == "cstate.id:":
++					latency = self._get_latency_by_cstate_id(latency[10:])
++				elif latency[0:12] == "cstate.name:":
++					latency = self._get_latency_by_cstate_name(latency[12:])
++				else:
++					latency = None
++					log.debug("invalid latency specified: '%s'" % str(latency))
++			if latency is not None:
++				break
++		return latency
++
+ 	def _set_latency(self, latency):
+-		latency = int(latency)
+-		if self._has_pm_qos and self._latency != latency:
+-			log.info("setting new cpu latency %d" % latency)
+-			latency_bin = struct.pack("i", latency)
+-			os.write(self._cpu_latency_fd, latency_bin)
+-			self._latency = latency
++		latency = self._parse_latency(latency)
++		if self._has_pm_qos:
++			if latency is None:
++				log.error("unable to evaluate latency value (probably wrong settings in the 'cpu' section of current profile), disabling PM QoS")
++				self._has_pm_qos = False
++			elif self._latency != latency:
++				log.info("setting new cpu latency %d" % latency)
++				latency_bin = struct.pack("i", latency)
++				os.write(self._cpu_latency_fd, latency_bin)
++				self._latency = latency
+ 
+ 	def _get_available_governors(self, device):
+ 		return self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_available_governors" % device).strip().split()
diff --git a/SPECS/tuned.spec b/SPECS/tuned.spec
index 063fbb3..7166b55 100644
--- a/SPECS/tuned.spec
+++ b/SPECS/tuned.spec
@@ -14,8 +14,10 @@
 
 %if %{with python3}
 %global _py python3
+%global make_python_arg PYTHON=%{__python3}
 %else
 %{!?python2_sitelib:%global python2_sitelib %{python_sitelib}}
+%global make_python_arg PYTHON=%{__python2}
 %if 0%{?rhel} && 0%{?rhel} < 8
 %global _py python
 %else
@@ -24,17 +26,17 @@
 %endif
 
 #%%global prerelease rc
-#%%global prereleasenum 2
+#%%global prereleasenum 1
 
 %global prerel1 %{?prerelease:.%{prerelease}%{prereleasenum}}
 %global prerel2 %{?prerelease:-%{prerelease}.%{prereleasenum}}
 
 Summary: A dynamic adaptive system tuning daemon
 Name: tuned
-Version: 2.10.0
-Release: 15%{?prerel1}%{?dist}
+Version: 2.12.0
+Release: 3%{?prerel1}%{?dist}
 License: GPLv2+
-Source0: https://github.com/redhat-performance/%{name}/archive/v%{version}%{?prerel2}.tar.gz#/%{name}-%{version}%{?prerel2}.tar.gz
+Source0: https://github.com/redhat-performance/%{name}/archive/v%{version}%{?prerel2}/%{name}-%{version}%{?prerel2}.tar.gz
 # RHEL-8 specific recommend.conf:
 Source1: recommend.conf
 URL: http://www.tuned-project.org/
@@ -61,34 +63,7 @@ Recommends: kernel-tools
 %if 0%{?rhel} > 7
 Requires: python3-syspurpose
 %endif
-
-# Upstream patch:
-Patch0: tuned-2.10.0-python-3.7-fix.patch
-# Upstream patch:
-Patch1: 0001-tuned-adm-Fix-a-traceback-when-run-without-action-sp.patch
-# Upstream patch:
-Patch2: tuned-2.10.0-makefile-full-python-path.patch
-# Upstream patch:
-Patch3: 0001-tuned-gui-Sort-plugins-based-on-their-name.patch
-Patch4: tuned-2.10.0-use-online-cpus.patch
-# Upstream patch:
-Patch5: 0001-Support-chassis-type-matching-in-recommend.conf.patch
-# Upstream patch:
-Patch6: 0002-Support-syspurpose-role-matching-in-recommend.conf.patch
-# Upstream patch:
-Patch7: 0001-Make-python-dmidecode-a-weak-dependency.patch
-Patch8: tuned-2.10.0-realtime-virtual-enable-rt-entsk.patch
-Patch9: tuned-2.10.0-disable-ksm-once.patch
-Patch10: tuned-2.10.0-update-kvm-modprobe-file.patch
-# Upstream patch:
-Patch11: tuned-2.10.0-add-support-for-bls.patch
-Patch12: tuned-2.10.0-s390x-bls-workaround.patch
-# https://github.com/redhat-performance/tuned/pull/144
-Patch13: 0001-scheduler-Keep-polling-file-objects-alive-long-enoug.patch
-# Upstream patch
-Patch14: tuned-2.10.0-mssql-tuning.patch
-# Upstream patch (2cc3d747986837d7e7957f5a4baede2dd691348a)
-Patch15: 0001-plugin_disk-Fix-checking-the-removable-attribute-on-.patch
+Patch0: tuned-2.12-latency-as-cstate.patch
 
 %description
 The tuned package contains a daemon that tunes system settings dynamically.
@@ -234,24 +209,6 @@ It can be also used to fine tune your system for specific scenarios.
 %prep
 %setup -q -n %{name}-%{version}%{?prerel2}
 %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
-%patch13 -p1
-%patch14 -p1
-%patch15 -p1
-
-# workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1626473 (maybe not needed)
-chmod 0755 profiles/realtime-virtual-guest/script.sh
 
 # Replace the upstream recommend.conf with a RHEL-8-specific one
 rm -f recommend.conf
@@ -260,12 +217,7 @@ cp -p %{SOURCE1} recommend.conf
 %build
 
 %install
-make install DESTDIR=%{buildroot} DOCDIR=%{docdir} \
-%if %{with python3}
-	PYTHON=%{__python3}
-%else
-	PYTHON=%{__python2}
-%endif
+make install DESTDIR=%{buildroot} DOCDIR=%{docdir} %{make_python_arg}
 %if 0%{?rhel}
 sed -i 's/\(dynamic_tuning[ \t]*=[ \t]*\).*/\10/' %{buildroot}%{_sysconfdir}/tuned/tuned-main.conf
 %endif
@@ -376,7 +328,6 @@ fi
 %exclude %{_sysconfdir}/tuned/realtime-virtual-guest-variables.conf
 %exclude %{_sysconfdir}/tuned/realtime-virtual-host-variables.conf
 %exclude %{_sysconfdir}/tuned/cpu-partitioning-variables.conf
-%exclude %{_sysconfdir}/tuned/sap-hana-vmware-variables.conf
 %exclude %{_prefix}/lib/tuned/default
 %exclude %{_prefix}/lib/tuned/desktop-powersave
 %exclude %{_prefix}/lib/tuned/laptop-ac-powersave
@@ -386,7 +337,6 @@ fi
 %exclude %{_prefix}/lib/tuned/spindown-disk
 %exclude %{_prefix}/lib/tuned/sap-netweaver
 %exclude %{_prefix}/lib/tuned/sap-hana
-%exclude %{_prefix}/lib/tuned/sap-hana-vmware
 %exclude %{_prefix}/lib/tuned/mssql
 %exclude %{_prefix}/lib/tuned/oracle
 %exclude %{_prefix}/lib/tuned/atomic-host
@@ -428,7 +378,6 @@ fi
 %{python2_sitelib}/tuned/gtk
 %endif
 %{_datadir}/tuned/ui
-%{_datadir}/polkit-1/actions/com.redhat.tuned.gui.policy
 %{_datadir}/icons/hicolor/scalable/apps/tuned.svg
 %{_datadir}/applications/tuned-gui.desktop
 
@@ -455,9 +404,7 @@ fi
 %{_mandir}/man7/tuned-profiles-sap.7*
 
 %files profiles-sap-hana
-%config(noreplace) %{_sysconfdir}/tuned/sap-hana-vmware-variables.conf
 %{_prefix}/lib/tuned/sap-hana
-%{_prefix}/lib/tuned/sap-hana-vmware
 %{_mandir}/man7/tuned-profiles-sap-hana.7*
 
 %files profiles-mssql
@@ -507,6 +454,42 @@ fi
 %{_mandir}/man7/tuned-profiles-compat.7*
 
 %changelog
+* Fri Aug 16 2019 Jaroslav Škarvada <jskarvad@redhat.com> - 2.12.0-3
+- used C-states in latency specification
+  related: rhbz#1737628
+
+* Fri Aug 16 2019 Jaroslav Škarvada <jskarvad@redhat.com> - 2.12.0-2
+- plugin_cpu: latency can be now specified as C-state
+  resolves: rhbz#1737628
+
+* Thu Jun 27 2019 Jaroslav Škarvada <jskarvad@redhat.com> - 2.12.0-1
+- new release
+  - rebased tuned to latest upstream
+    related: rhbz#1685585
+
+* Wed Jun 12 2019 Jaroslav Škarvada <jskarvad@redhat.com> - 2.12.0-0.1.rc1
+- new release
+  - rebased tuned to latest upstream
+    resolves: rhbz#1685585
+  - sap-netweaver: changed values of kernel.shmall and kernel.shmmax to RHEL-8 defaults
+    resolves: rhbz#1708418
+  - sap-netweaver: changed value of kernel.sem to RHEL-8 default
+    resolves: rhbz#1701394
+  - sap-hana-vmware: dropped profile
+    resolves: rhbz#1715541
+  - s2kb function: fixed to be compatible with python3
+    resolves: rhbz#1684122
+  - do fallback to the powersave governor (balanced and powersave profiles)
+    resolves: rhbz#1679205
+  - added support for negation of CPU list
+    resolves: rhbz#1676588
+  - switched from sysctl tool to own implementation
+    resolves: rhbz#1666678
+  - realtime-virtual-host: added tsc-deadline=on to qemu cmdline
+    resolves: rhbz#1554458
+  - fixed handling of devices that have been removed and re-attached
+    resolves: rhbz#1677730
+
 * Fri Feb 22 2019 Jaroslav Škarvada <jskarvad@redhat.com> - 2.10.0-15
 - Fixed disk plugin to correctly match devices with python3
   Resolves: rhbz#1676513