tuned: Forward ported patches from ph4

Change-Id: I0894fcae9467e6fec90aaa85618a017ed1307ef9
Signed-off-by: Keerthana K <keerthanak@vmware.com>
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/19137
Reviewed-by: Srivatsa S. Bhat <srivatsab@vmware.com>
Tested-by: Srivatsa S. Bhat <srivatsab@vmware.com>
This commit is contained in:
Keerthana K 2023-01-12 08:57:43 +00:00 committed by Srivatsa S. Bhat
parent 3595ac0692
commit 804405b18b
4 changed files with 320 additions and 2 deletions

View File

@ -0,0 +1,134 @@
From 4e2782e32413c5060ed409a0b284e6250d1a8df7 Mon Sep 17 00:00:00 2001
From: Keerthana K <keerthanak@vmware.com>
Date: Mon, 23 Aug 2021 14:03:08 +0000
Subject: [PATCH] Schedule perf events iff scheduler per process configurations
are set
Tuned scheduler plugin registers for process creation and exit
(perf.RECORD_COMM and perf.RECORD_EXIT) perf events during plugin init
(`_instance_init`) if runtime scheduling is not disabled explicitly.
By default, runtime tuning is set true in tuned code, if not disabled
explicitly in tuned profile conf file.
It also creates a thread and polls for the perf events and checks whether
it is of perf.RECORD_COMM or perf.RECORD_EXIT type in `_instance_apply_static`
function if runtime scheduling is enabled. This thread runs indefinitely
till the tuned process is terminated and keeps polling for these perf events.
When these events are hit, tuned code checks whether the created process name
matches the regex configured from tuned.conf and tunes these processes with
configured scheduler_priority, affinity and policy.
Even when these are not configured in tuned.conf, scheduler plugin creates
perf events and creates this polling thread and returns from tune_process function
as there is no process tuning configurations set. Basically, it just polls for
these events and does nothing.
Perf events ((perf.RECORD_COMM and perf.RECORD_EXIT) created by tuned causes OS jitter
in realtime kernel. When a RT task is started to run, perf events (perf_event_comm_output())
registered through tuned wakes up tasks through irq_work() which causes ktimersoftd in
isolated cores. This causes jitter in isolated cores. Apart from this, whenever a process
is created/changed or exited the perf events registered through tuned causes jitter.
To fix this issue, perf events scheduling code is moved from `_instance_init` to
_instance_apply_static` function where the thread is created to poll on these events
and a new check is added to verify whether the scheduler configurations
(process_name, prio, policy, affinity) from tuned.conf is not null and then
schedule perf events and create thread.
Signed-off-by: Keerthana K <keerthanak@vmware.com>
---
tuned/plugins/plugin_scheduler.py | 59 +++++++++++++++----------------
1 file changed, 29 insertions(+), 30 deletions(-)
diff --git a/tuned/plugins/plugin_scheduler.py b/tuned/plugins/plugin_scheduler.py
index 32b9c1a..6440a74 100644
--- a/tuned/plugins/plugin_scheduler.py
+++ b/tuned/plugins/plugin_scheduler.py
@@ -126,37 +126,11 @@ class SchedulerPlugin(base.Plugin):
instance._scheduler = instance.options
- perf_mmap_pages_raw = self._variables.expand(instance.options["perf_mmap_pages"])
- perf_mmap_pages = self._calc_mmap_pages(perf_mmap_pages_raw)
- if perf_mmap_pages == 0:
- log.error("Invalid 'perf_mmap_pages' value specified: '%s', using default kernel value" % perf_mmap_pages_raw)
- perf_mmap_pages = None
- if perf_mmap_pages is not None and str(perf_mmap_pages) != perf_mmap_pages_raw:
- log.info("'perf_mmap_pages' value has to be power of two, specified: '%s', using: '%d'" %
- (perf_mmap_pages_raw, perf_mmap_pages))
for k in instance._scheduler:
instance._scheduler[k] = self._variables.expand(instance._scheduler[k])
if self._cmd.get_bool(instance._scheduler.get("runtime", 1)) == "0":
instance._runtime_tuning = False
instance._terminate = threading.Event()
- if self._daemon and instance._runtime_tuning:
- try:
- instance._threads = perf.thread_map()
- evsel = perf.evsel(type = perf.TYPE_SOFTWARE,
- config = perf.COUNT_SW_DUMMY,
- task = 1, comm = 1, mmap = 0, freq = 0,
- wakeup_events = 1, watermark = 1,
- sample_type = perf.SAMPLE_TID | perf.SAMPLE_CPU)
- evsel.open(cpus = self._cpus, threads = instance._threads)
- instance._evlist = perf.evlist(self._cpus, instance._threads)
- instance._evlist.add(evsel)
- if perf_mmap_pages is None:
- instance._evlist.mmap()
- else:
- instance._evlist.mmap(pages = perf_mmap_pages)
- # no perf
- except:
- instance._runtime_tuning = False
def _instance_cleanup(self, instance):
pass
@@ -575,9 +549,34 @@ class SchedulerPlugin(base.Plugin):
priority, affinity)
self._storage.set(self._scheduler_storage_key,
self._scheduler_original)
- if self._daemon and instance._runtime_tuning:
- instance._thread = threading.Thread(target = self._thread_code, args = [instance])
- instance._thread.start()
+ if self._daemon and instance._runtime_tuning and bool(instance._sched_lookup):
+ perf_mmap_pages_raw = self._variables.expand(instance.options["perf_mmap_pages"])
+ perf_mmap_pages = self._calc_mmap_pages(perf_mmap_pages_raw)
+ if perf_mmap_pages == 0:
+ log.error("Invalid 'perf_mmap_pages' value specified: '%s', using default kernel value" % perf_mmap_pages_raw)
+ perf_mmap_pages = None
+ if perf_mmap_pages is not None and str(perf_mmap_pages) != perf_mmap_pages_raw:
+ log.info("'perf_mmap_pages' value has to be power of two, specified: '%s', using: '%d'" %
+ (perf_mmap_pages_raw, perf_mmap_pages))
+ try:
+ instance._threads = perf.thread_map()
+ evsel = perf.evsel(type = perf.TYPE_SOFTWARE,
+ config = perf.COUNT_SW_DUMMY,
+ task = 1, comm = 1, mmap = 0, freq = 0,
+ wakeup_events = 1, watermark = 1,
+ sample_type = perf.SAMPLE_TID | perf.SAMPLE_CPU)
+ evsel.open(cpus = self._cpus, threads = instance._threads)
+ instance._evlist = perf.evlist(self._cpus, instance._threads)
+ instance._evlist.add(evsel)
+ if perf_mmap_pages is None:
+ instance._evlist.mmap()
+ else:
+ instance._evlist.mmap(pages = perf_mmap_pages)
+ instance._thread = threading.Thread(target = self._thread_code, args = [instance])
+ instance._thread.start()
+ # no perf
+ except:
+ instance._runtime_tuning = False
def _restore_ps_affinity(self):
try:
@@ -622,7 +621,7 @@ class SchedulerPlugin(base.Plugin):
def _instance_unapply_static(self, instance, full_rollback = False):
super(SchedulerPlugin, self)._instance_unapply_static(instance, full_rollback)
- if self._daemon and instance._runtime_tuning:
+ if self._daemon and instance._runtime_tuning and bool(instance._sched_lookup):
instance._terminate.set()
instance._thread.join()
self._restore_ps_affinity()
--
2.28.0

View File

@ -0,0 +1,34 @@
From c66900664e5a0ae5a9894777d8e4b0f2300af95a Mon Sep 17 00:00:00 2001
From: Ankit Jain <ankitja@vmware.com>
Date: Thu, 21 Oct 2021 09:27:53 +0000
Subject: [PATCH] realtime: Modify hung_task detection param
- For realtime system, we wanted to capture
stack trace if a task remain in D-state for
30 seconds or more for debugging purpose.
- To log infinite number of times, set
hung_task_warnings to -1
Signed-off-by: Ankit Jain <ankitja@vmware.com>
Signed-off-by: Keerthana K <keerthanak@vmware.com>
---
profiles/realtime/tuned.conf | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/profiles/realtime/tuned.conf b/profiles/realtime/tuned.conf
index 8eed36e..f9c6883 100644
--- a/profiles/realtime/tuned.conf
+++ b/profiles/realtime/tuned.conf
@@ -39,7 +39,8 @@ managed_irq=${f:regex_search_ternary:${isolate_managed_irq}:\b[y,Y,1,t,T]\b:mana
channels=combined ${f:check_net_queue_count:${netdev_queue_count}}
[sysctl]
-kernel.hung_task_timeout_secs = 600
+kernel.hung_task_timeout_secs = 30
+kernel.hung_task_warnings = -1
kernel.nmi_watchdog = 0
kernel.sched_rt_runtime_us = -1
vm.stat_interval = 10
--
2.23.1

View File

@ -0,0 +1,142 @@
From 223cc69c24da094b01e3b371ea67a994db3f05ae Mon Sep 17 00:00:00 2001
From: Him Kalyan Bordoloi <bordoloih@vmware.com>
Date: Thu, 24 Sep 2020 16:45:22 -0700
Subject: [PATCH] bootloader plugin support for photon
Signed-off-by: Him Kalyan Bordoloi <bordoloih@vmware.com>
Signed-off-by: Keerthana K <keerthanak@vmware.com>
---
Makefile | 1 +
tuned.cfg | 3 +++
tuned/consts.py | 3 ++-
tuned/plugins/plugin_bootloader.py | 11 +++++++++--
tuned/utils/commands.py | 15 +++++++++++++++
5 files changed, 30 insertions(+), 3 deletions(-)
create mode 100644 tuned.cfg
diff --git a/Makefile b/Makefile
index 9ee7bcc..3a51c8c 100644
--- a/Makefile
+++ b/Makefile
@@ -165,6 +165,7 @@ install: install-dirs
echo -n > $(DESTDIR)$(SYSCONFDIR)/tuned/post_loaded_profile
install -Dpm 0644 bootcmdline $(DESTDIR)$(SYSCONFDIR)/tuned/bootcmdline
install -Dpm 0644 modules.conf $(DESTDIR)$(SYSCONFDIR)/modprobe.d/tuned.conf
+ install -Dpm 0644 tuned.cfg $(DESTDIR)/boot/tuned.cfg
# profiles & system config
cp -a profiles/* $(DESTDIR)$(TUNED_PROFILESDIR)/
diff --git a/tuned.cfg b/tuned.cfg
new file mode 100644
index 0000000..5ea7c08
--- /dev/null
+++ b/tuned.cfg
@@ -0,0 +1,3 @@
+# GRUB Environment Block
+tuned_params=
+tuned_initrd=
diff --git a/tuned/consts.py b/tuned/consts.py
index f7a082e..18ddb2e 100644
--- a/tuned/consts.py
+++ b/tuned/consts.py
@@ -24,7 +24,7 @@ ERROR_THRESHOLD = 3
# bootloader plugin configuration
BOOT_DIR = "/boot"
-GRUB2_CFG_FILES = ["/etc/grub2.cfg", "/etc/grub2-efi.cfg"]
+GRUB2_CFG_FILES = ["/etc/grub2.cfg", "/etc/grub2-efi.cfg", "/boot/grub2/grub.cfg"]
GRUB2_CFG_DIR = "/etc/grub.d"
GRUB2_TUNED_TEMPLATE_NAME = "00_tuned"
GRUB2_TUNED_TEMPLATE_PATH = GRUB2_CFG_DIR + "/" + GRUB2_TUNED_TEMPLATE_NAME
@@ -41,6 +41,7 @@ PETITBOOT_DETECT_DIR = "/sys/firmware/opal"
MACHINE_ID_FILE = "/etc/machine-id"
KERNEL_UPDATE_HOOK_FILE = "/usr/lib/kernel/install.d/92-tuned.install"
BLS_ENTRIES_PATH = "/boot/loader/entries"
+PHOTON_TUNED_CFG_FILE = "/boot/tuned.cfg"
# scheduler plugin configuration
# how many times retry to move tasks to parent cgroup on cgroup cleanup
diff --git a/tuned/plugins/plugin_bootloader.py b/tuned/plugins/plugin_bootloader.py
index 416df7d..c73c827 100644
--- a/tuned/plugins/plugin_bootloader.py
+++ b/tuned/plugins/plugin_bootloader.py
@@ -20,8 +20,8 @@ class BootloaderPlugin(base.Plugin):
"""
def __init__(self, *args, **kwargs):
- if not os.path.isfile(consts.GRUB2_TUNED_TEMPLATE_PATH):
- raise exceptions.NotSupportedPluginException("Required GRUB2 template not found, disabling plugin.")
+ if not os.path.isfile(consts.PHOTON_TUNED_CFG_FILE):
+ raise exceptions.NotSupportedPluginException("Required GRUB2 tuned config not found, disabling plugin.")
super(BootloaderPlugin, self).__init__(*args, **kwargs)
self._cmd = commands()
@@ -98,11 +98,15 @@ class BootloaderPlugin(base.Plugin):
return re.search(r"^\s*GRUB_ENABLE_BLSCFG\s*=\s*\"?\s*[tT][rR][uU][eE]\s*\"?\s*$", grub2_default_env,
flags = re.MULTILINE) is not None
+ def _patch_photon_tuned_cfg(self, d):
+ return self._cmd.add_modify_option_woquotes_in_file(consts.PHOTON_TUNED_CFG_FILE, d)
+
def _patch_bootcmdline(self, d):
return self._cmd.add_modify_option_in_file(consts.BOOT_CMDLINE_FILE, d)
def _remove_grub2_tuning(self):
self._patch_bootcmdline({consts.BOOT_CMDLINE_TUNED_VAR : "", consts.BOOT_CMDLINE_INITRD_ADD_VAR : ""})
+ self._patch_photon_tuned_cfg({consts.GRUB2_TUNED_VAR : "", consts.GRUB2_TUNED_INITRD_VAR : ""})
if not self._grub2_cfg_file_names:
log.info("cannot find grub.cfg to patch")
return
@@ -124,6 +128,7 @@ class BootloaderPlugin(base.Plugin):
grub2_cfg = re.sub(r" *\$" + consts.GRUB2_TUNED_VAR, "", cfg, flags = re.MULTILINE)
cfg = re.sub(r"^\s*set\s+" + consts.GRUB2_TUNED_INITRD_VAR + "\s*=.*\n", "", grub2_cfg, flags = re.MULTILINE)
grub2_cfg = re.sub(r" *\$" + consts.GRUB2_TUNED_INITRD_VAR, "", cfg, flags = re.MULTILINE)
+ grub2_cfg = re.sub(r'(?m).*tuned.cfg\n?', '', grub2_cfg)
cfg = re.sub(consts.GRUB2_TEMPLATE_HEADER_BEGIN + r"\n", "", grub2_cfg, flags = re.MULTILINE)
return re.sub(consts.GRUB2_TEMPLATE_HEADER_END + r"\n+", "", cfg, flags = re.MULTILINE)
@@ -135,6 +140,7 @@ class BootloaderPlugin(base.Plugin):
s += consts.GRUB2_TEMPLATE_HEADER_END + r"\n"
grub2_cfg = re.sub(r"^(\s*###\s+END\s+[^#]+/00_header\s+### *)\n", s, grub2_cfg, flags = re.MULTILINE)
+ grub2_cfg = re.sub(r"(load_env -f /boot/photon.cfg)" , r"\1\nload_env -f /boot/tuned.cfg", grub2_cfg)
d2 = {"linux" : consts.GRUB2_TUNED_VAR, "initrd" : consts.GRUB2_TUNED_INITRD_VAR}
for i in d2:
# add TuneD parameters to all kernels
@@ -217,6 +223,7 @@ class BootloaderPlugin(base.Plugin):
def _grub2_update(self):
self._grub2_cfg_patch({consts.GRUB2_TUNED_VAR : self._cmdline_val, consts.GRUB2_TUNED_INITRD_VAR : self._initrd_val})
+ self._patch_photon_tuned_cfg({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):
diff --git a/tuned/utils/commands.py b/tuned/utils/commands.py
index df695a7..ce34997 100644
--- a/tuned/utils/commands.py
+++ b/tuned/utils/commands.py
@@ -206,6 +206,21 @@ class commands:
data = self.read_file(f)
return hashlib.sha256(str(data).encode("utf-8")).hexdigest()
+ def add_modify_option_woquotes_in_file(self, f, d, add = True):
+ data = self.read_file(f)
+ for opt in d:
+ o = str(opt)
+ v = str(d[opt])
+ if re.search(r"\b" + o + r"\s*=.*$", data, flags = re.MULTILINE) is None:
+ if add:
+ if len(data) > 0 and data[-1] != "\n":
+ data += "\n"
+ data += "%s=%s\n" % (o, v)
+ else:
+ data = re.sub(r"\b(" + o + r"\s*=).*$", r"\1" + v, data, flags = re.MULTILINE)
+
+ 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()
--
2.23.1

View File

@ -1,6 +1,6 @@
Name: tuned
Version: 2.19.0
Release: 4%{?dist}
Release: 5%{?dist}
Summary: A dynamic adaptive system tuning daemon
License: GNU GENERAL PUBLIC LICENSE Version 2
Group: System/Base
@ -13,6 +13,9 @@ Source0: tuned-%{version}.tar.gz
Patch0: remove_desktop_utils_dependency.patch
Patch1: tuned-fix-bug-in-sysctl-verify.patch
Patch2: bootloader-plugin-support-for-photon.patch
Patch3: 0001-Schedule-perf-events-iff-scheduler-per-process-confi.patch
Patch4: 0001-realtime-Modify-hung_task-detection-param.patch
BuildRequires: python3-devel
BuildRequires: systemd-devel
@ -110,14 +113,16 @@ make test %{?_smp_mflags}
%config(noreplace) %{_sysconfdir}/tuned/tuned-main.conf
%config(noreplace) %{_sysconfdir}/dbus-1/system.d/com.redhat.tuned.conf
%config(noreplace) %{_sysconfdir}/modprobe.d/tuned.conf
%config(noreplace) /boot/tuned.cfg
%config(noreplace) %{_sysconfdir}/tuned/
%{_libdir}/tmpfiles.d
%{_unitdir}/tuned.service
%dir %{_localstatedir}/log/tuned
%dir /etc/tuned
%dir /var/lib/tuned
%{_mandir}/man5/tuned*
%{_mandir}/man8/tuned*
%{_datadir}/tuned/grub2
%{_sysconfdir}/tuned
%{_libdir}/tuned/
%{_datadir}/doc
%exclude %{_datadir}/icons/hicolor/scalable/apps/tuned.svg
@ -141,6 +146,9 @@ make test %{?_smp_mflags}
%{_mandir}/man8/scomes.*
%changelog
* Thu Jan 12 2023 Keerthana K <keerthanak@vmware.com> 2.19.0-5
- Forward port patches from ph4
- Add /var/lib/tuned to rpm
* Tue Dec 06 2022 Prashant S Chauhan <psinghchauha@vmware.com> 2.19.0-4
- Update release to compile with python 3.11
* Fri Dec 02 2022 Srinidhi Rao <srinidhir@vmware.com> 2.19.0-3