1
0
Fork 0
tuned/profiles/functions
Ondřej Lysoněk 1b80d4eac2 Disable KSM only once, re-enable it only on full rollback
Disabling the ksm and ksmtuned services during boot seems to cause
problems, so do it only once when the profile is first applied and
reenable the services only when full rollback is required.

Resolves: rhbz#1622239

Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
2018-11-21 11:27:44 +01:00

620 lines
14 KiB
Text

#
# This is library of helper functions that can be used in scripts in tuned profiles.
#
# API provided by this library is under heavy development and could be changed anytime
#
#
# Config
#
STORAGE=/run/tuned
STORAGE_PERSISTENT=/var/lib/tuned
STORAGE_SUFFIX=".save"
#
# Helpers
#
# Save value
# $0 STORAGE_NAME VALUE
save_value() {
[ "$#" -ne 2 ] && return
[ "$2" -a -e "${STORAGE}" ] && echo "$2" > "${STORAGE}/${1}${STORAGE_SUFFIX}"
}
# Parse sysfs value, i.e. for "val1 [val2] val3" return "val2"
# $0 SYSFS_NAME
parse_sys() {
local V1 V2
[ -r "$1" ] || return
V1=`cat "$1"`
V2="${V1##*[}"
V2="${V2%%]*}"
echo "${V2:-$V1}"
}
# Save sysfs value
# $0 STORAGE_NAME SYSFS_NAME
save_sys() {
[ "$#" -ne 2 ] && return
[ -r "$2" -a ! -e "${STORAGE}/${1}${STORAGE_SUFFIX}" ] && parse_sys "$2" > "${STORAGE}/${1}${STORAGE_SUFFIX}"
}
# Set sysfs value
# $0 SYSFS_NAME VALUE
set_sys() {
[ "$#" -ne 2 ] && return
[ -w "$1" ] && echo "$2" > "$1"
}
# Save and set sysfs value
# $0 STORAGE_NAME SYSFS_NAME VALUE
save_set_sys() {
[ "$#" -ne 3 ] && return
save_sys "$1" "$2"
set_sys "$2" "$3"
}
# Get stored sysfs value from storage
# $0 STORAGE_NAME
get_stored_sys() {
[ "$#" -ne 1 ] && return
[ -r "${STORAGE}/${1}${STORAGE_SUFFIX}" ] && cat "${STORAGE}/${1}${STORAGE_SUFFIX}"
}
# Restore value from storage
# $0 STORAGE_NAME
restore_value() {
[ "$#" -ne 1 ] && return
_rs_value="`get_stored_sys \"$1\"`"
unlink "${STORAGE}/${1}${STORAGE_SUFFIX}" >/dev/null 2>&1
[ "$_rs_value" ] && echo "$_rs_value"
}
# Restore sysfs value from storage, if nothing is stored, use VALUE
# $0 STORAGE_NAME SYSFS_NAME [VALUE]
restore_sys() {
[ "$#" -lt 2 -o "$#" -gt 3 ] && return
_rs_value="`get_stored_sys \"$1\"`"
unlink "${STORAGE}/${1}${STORAGE_SUFFIX}" >/dev/null 2>&1
[ "$_rs_value" ] || _rs_value="$3"
[ "$_rs_value" ] && set_sys "$2" "$_rs_value"
}
#
# DISK tuning
#
DISKS_DEV="$(command ls -d1 /dev/[shv]d*[a-z] 2>/dev/null)"
DISKS_SYS="$(command ls -d1 /sys/block/{sd,cciss,dm-,vd,dasd,xvd}* 2>/dev/null)"
_check_elevator_override()
{
/bin/fgrep -q 'elevator=' /proc/cmdline
}
# $0 OPERATOR DEVICES ELEVATOR
_set_elevator_helper() {
_check_elevator_override && return
SYS_BLOCK_SDX=""
[ "$2" ] && SYS_BLOCK_SDX=$(eval LANG=C /bin/ls -1 "${2}" 2>/dev/null)
# if there is no kernel command line elevator settings, apply the elevator
if [ "$1" -a "$SYS_BLOCK_SDX" ]; then
for i in $SYS_BLOCK_SDX; do
se_dev="`echo \"$i\" | sed 's|/sys/block/\([^/]\+\)/queue/scheduler|\1|'`"
$1 "elevator_${se_dev}" "$i" "$3"
done
fi
}
# $0 DEVICES ELEVATOR
set_elevator() {
_set_elevator_helper save_set_sys "$1" "$2"
}
# $0 DEVICES [ELEVATOR]
restore_elevator() {
re_elevator="$2"
[ "$re_elevator" ] || re_elevator=cfq
_set_elevator_helper restore_sys "$1" "$re_elevator"
}
# SATA Aggressive Link Power Management
# usage: set_disk_alpm policy
set_disk_alpm() {
policy=$1
for host in /sys/class/scsi_host/*; do
if [ -f $host/ahci_port_cmd ]; then
port_cmd=`cat $host/ahci_port_cmd`;
if [ $((0x$port_cmd & 0x240000)) = 0 -a -f $host/link_power_management_policy ]; then
echo $policy >$host/link_power_management_policy;
else
echo "max_performance" >$host/link_power_management_policy;
fi
fi
done
}
# usage: set_disk_apm level
set_disk_apm() {
level=$1
for disk in $DISKS_DEV; do
hdparm -B $level $disk &>/dev/null
done
}
# usage: set_disk_spindown level
set_disk_spindown() {
level=$1
for disk in $DISKS_DEV; do
hdparm -S $level $disk &>/dev/null
done
}
# usage: multiply_disk_readahead by
multiply_disk_readahead() {
by=$1
# float multiplication not supported in bash
# bc might not be installed, python is available for sure
for disk in $DISKS_SYS; do
control="${disk}/queue/read_ahead_kb"
old=$(cat $control)
new=$(echo "print int($old*$by)" | python)
(echo $new > $control) &>/dev/null
done
}
# usage: remount_disk options partition1 partition2 ...
remount_partitions() {
options=$1
shift
for partition in $@; do
mount -o remount,$options $partition >/dev/null 2>&1
done
}
remount_all_no_rootboot_partitions() {
[ "$1" ] || return
# Find non-root and non-boot partitions, disable barriers on them
rootvol=$(df -h / | grep "^/dev" | awk '{print $1}')
bootvol=$(df -h /boot | grep "^/dev" | awk '{print $1}')
volumes=$(df -hl --exclude=tmpfs | grep "^/dev" | awk '{print $1}')
nobarriervols=$(echo "$volumes" | grep -v $rootvol | grep -v $bootvol)
remount_partitions "$1" $nobarriervols
}
DISK_QUANTUM_SAVE="${STORAGE}/disk_quantum${STORAGE_SUFFIX}"
set_disk_scheduler_quantum() {
value=$1
rm -f "$DISK_QUANTUM_SAVE"
for disk in $DISKS_SYS; do
control="${disk}/queue/iosched/quantum"
echo "echo $(cat $control) > $control" >> "$DISK_QUANTUM_SAVE" 2>/dev/null
(echo $value > $control) &2>/dev/null
done
}
restore_disk_scheduler_quantum() {
if [ -r "$DISK_QUANTUM_SAVE" ]; then
/bin/sh "$DISK_QUANTUM_SAVE" &>/dev/null
rm -f "$DISK_QUANTUM_SAVE"
fi
}
#
# CPU tuning
#
CPUSPEED_SAVE_FILE="${STORAGE}/cpuspeed${STORAGE_SUFFIX}"
CPUSPEED_ORIG_GOV="${STORAGE}/cpuspeed-governor-%s${STORAGE_SUFFIX}"
CPUSPEED_STARTED="${STORAGE}/cpuspeed-started"
CPUSPEED_CFG="/etc/sysconfig/cpuspeed"
CPUSPEED_INIT="/etc/init.d/cpuspeed"
# do not use cpuspeed
CPUSPEED_USE="0"
CPUS="$(ls -d1 /sys/devices/system/cpu/cpu* | sed 's;^.*/;;' | grep "cpu[0-9]\+")"
# set CPU governor setting and store the old settings
# usage: set_cpu_governor governor
set_cpu_governor() {
governor=$1
# always patch cpuspeed configuration if exists, if it doesn't exist and is enabled,
# explictly disable it with hint
if [ -e $CPUSPEED_INIT ]; then
if [ ! -e $CPUSPEED_SAVE_FILE -a -e $CPUSPEED_CFG ]; then
cp -p $CPUSPEED_CFG $CPUSPEED_SAVE_FILE
sed -e 's/^GOVERNOR=.*/GOVERNOR='$governor'/g' $CPUSPEED_SAVE_FILE > $CPUSPEED_CFG
fi
else
if [ "$CPUSPEED_USE" = "1" ]; then
echo >&2
echo "Suggestion: install 'cpuspeed' package to get best tuning results." >&2
echo "Falling back to sysfs control." >&2
echo >&2
fi
CPUSPEED_USE="0"
fi
if [ "$CPUSPEED_USE" = "1" ]; then
service cpuspeed status &> /dev/null
[ $? -eq 3 ] && touch $CPUSPEED_STARTED || rm -f $CPUSPEED_STARTED
service cpuspeed restart &> /dev/null
# direct change using sysfs
elif [ -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]; then
for cpu in $CPUS; do
gov_file=/sys/devices/system/cpu/$cpu/cpufreq/scaling_governor
save_file=$(printf $CPUSPEED_ORIG_GOV $cpu)
rm -f $save_file
if [ -e $gov_file ]; then
cat $gov_file > $save_file
echo $governor > $gov_file
fi
done
fi
}
# re-enable previous CPU governor settings
# usage: restore_cpu_governor
restore_cpu_governor() {
if [ -e $CPUSPEED_INIT ]; then
if [ -e $CPUSPEED_SAVE_FILE ]; then
cp -fp $CPUSPEED_SAVE_FILE $CPUSPEED_CFG
rm -f $CPUSPEED_SAVE_FILE
fi
if [ "$CPUSPEED_USE" = "1" ]; then
if [ -e $CPUSPEED_STARTED ]; then
service cpuspeed stop &> /dev/null
else
service cpuspeed restart &> /dev/null
fi
fi
if [ -e $CPUSPEED_STARTED ]; then
rm -f $CPUSPEED_STARTED
fi
else
CPUSPEED_USE="0"
fi
if [ "$CPUSPEED_USE" != "1" -a -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]; then
for cpu in $CPUS; do
cpufreq_dir=/sys/devices/system/cpu/$cpu/cpufreq
save_file=$(printf $CPUSPEED_ORIG_GOV $cpu)
if [ -e $cpufreq_dir/scaling_governor ]; then
if [ -e $save_file ]; then
cat $save_file > $cpufreq_dir/scaling_governor
rm -f $save_file
else
echo userspace > $cpufreq_dir/scaling_governor
cat $cpufreq_dir/cpuinfo_max_freq > $cpufreq_dir/scaling_setspeed
fi
fi
done
fi
}
_cpu_multicore_powersave() {
value=$1
[ -e /sys/devices/system/cpu/sched_mc_power_savings ] && echo $value > /sys/devices/system/cpu/sched_mc_power_savings
}
# enable multi core power savings for low wakeup systems
enable_cpu_multicore_powersave() {
_cpu_multicore_powersave 1
}
disable_cpu_multicore_powersave() {
_cpu_multicore_powersave 0
}
#
# MEMORY tuning
#
THP_ENABLE="/sys/kernel/mm/transparent_hugepage/enabled"
THP_SAVE="${STORAGE}/thp${STORAGE_SUFFIX}"
[ -e "$THP_ENABLE" ] || THP_ENABLE="/sys/kernel/mm/redhat_transparent_hugepage/enabled"
enable_transparent_hugepages() {
if [ -e $THP_ENABLE ]; then
cut -f2 -d'[' $THP_ENABLE | cut -f1 -d']' > $THP_SAVE
(echo always > $THP_ENABLE) &> /dev/null
fi
}
restore_transparent_hugepages() {
if [ -e $THP_SAVE ]; then
(echo $(cat $THP_SAVE) > $THP_ENABLE) &> /dev/null
rm -f $THP_SAVE
fi
}
#
# WIFI tuning
#
# usage: _wifi_set_power_level level
_wifi_set_power_level() {
# 0 auto, PM enabled
# 1-5 least savings and lowest latency - most savings and highest latency
# 6 disable power savings
level=$1
# apply the settings using iwpriv
ifaces=$(cat /proc/net/wireless | grep -v '|' | sed 's@^ *\([^:]*\):.*@\1@')
for iface in $ifaces; do
iwpriv $iface set_power $level
done
# some adapters may relay on sysfs
for i in /sys/bus/pci/devices/*/power_level; do
(echo $level > $i) &> /dev/null
done
}
enable_wifi_powersave() {
_wifi_set_power_level 5
}
disable_wifi_powersave() {
_wifi_set_power_level 0
}
#
# BLUETOOTH tuning
#
disable_bluetooth() {
hciconfig hci0 down >/dev/null 2>&1
lsmod | grep -q btusb && rmmod btusb
}
enable_bluetooth() {
modprobe btusb
hciconfig hci0 up >/dev/null 2>&1
}
#
# USB tuning
#
_usb_autosuspend() {
value=$1
for i in /sys/bus/usb/devices/*/power/autosuspend; do echo $value > $i; done &> /dev/null
}
enable_usb_autosuspend() {
_usb_autosuspend 1
}
disable_usb_autosuspend() {
_usb_autosuspend 0
}
#
# SOUND CARDS tuning
#
enable_snd_ac97_powersave() {
save_set_sys ac97 /sys/module/snd_ac97_codec/parameters/power_save Y
}
disable_snd_ac97_powersave() {
save_set_sys ac97 /sys/module/snd_ac97_codec/parameters/power_save N
}
restore_snd_ac97_powersave() {
restore_sys ac97 /sys/module/snd_ac97_codec/parameters/power_save $1
}
set_hda_intel_powersave() {
save_set_sys hda_intel /sys/module/snd_hda_intel/parameters/power_save $1
}
restore_hda_intel_powersave() {
restore_sys hda_intel /sys/module/snd_hda_intel/parameters/power_save $1
}
#
# VIDEO CARDS tuning
#
# Power savings settings for Radeon
# usage: set_radeon_powersave dynpm | default | low | mid | high
set_radeon_powersave () {
[ "$1" ] || return
[ -e /sys/class/drm/card0/device/power_method ] || return
if [ "$1" = default -o "$1" = auto -o "$1" = low -o "$1" = med -o "$1" = high ]; then
[ -w /sys/class/drm/card0/device/power_profile ] || return
save_sys radeon_profile /sys/class/drm/card0/device/power_profile
save_set_sys radeon_method /sys/class/drm/card0/device/power_method profile
set_sys /sys/class/drm/card0/device/power_profile "$1"
elif [ "$1" = dynpm ]; then
save_sys radeon_profile /sys/class/drm/card0/device/power_profile
save_set_sys radeon_method /sys/class/drm/card0/device/power_method dynpm
fi
}
restore_radeon_powersave () {
restore_sys radeon_method /sys/class/drm/card0/device/power_method profile
_rrp_method="`get_stored_sys radeon_method`"
[ -z "$_rrp_method" -o _rrp_method="profile" ] && restore_sys radeon_profile /sys/class/drm/card0/device/power_profile default
}
#
# SOFTWARE tuning
#
RSYSLOG_CFG="/etc/rsyslog.conf"
RSYSLOG_SAVE="${STORAGE}/cpuspeed${STORAGE_SUFFIX}"
disable_logs_syncing() {
cp -p $RSYSLOG_CFG $RSYSLOG_SAVE
sed -i 's/ \/var\/log/-\/var\/log/' $RSYSLOG_CFG
}
restore_logs_syncing() {
mv -Z $RSYSLOG_SAVE $RSYSLOG_CFG || mv $RSYSLOG_SAVE $RSYSLOG_CFG
}
#
# HARDWARE SPECIFIC tuning
#
# Asus EEE with Intel Atom
_eee_fsb_control() {
value=$1
if [ -e /sys/devices/platform/eeepc/she ]; then
echo $value > /sys/devices/platform/eeepc/she
elif [ -e /sys/devices/platform/eeepc/cpufv ]; then
echo $value > /sys/devices/platform/eeepc/cpufv
elif [ -e /sys/devices/platform/eeepc-wmi/cpufv ]; then
echo $value > /sys/devices/platform/eeepc-wmi/cpufv
fi
}
eee_set_reduced_fsb() {
_eee_fsb_control 2
}
eee_set_normal_fsb() {
_eee_fsb_control 1
}
#
# modprobe configuration handling
#
kvm_modprobe_file=/etc/modprobe.d/kvm.rt.tuned.conf
setup_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
}
teardown_kvm_mod_low_latency()
{
rm -f $kvm_modprobe_file
}
#
# KSM
#
KSM_SERVICES="ksm ksmtuned"
KSM_RUN_PATH=/sys/kernel/mm/ksm/run
KSM_MASK_FILE="${STORAGE_PERSISTENT}/ksm-masked"
disable_ksm()
{
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
systemctl --now --quiet mask $KSM_SERVICES
# Unmerge all shared pages
test -f $KSM_RUN_PATH && echo 2 > $KSM_RUN_PATH
fi
}
# Should only be called when full_rollback == true
enable_ksm()
{
if [ -f $KSM_MASK_FILE ]; then
if systemctl --quiet unmask $KSM_SERVICES; then
rm -f $KSM_MASK_FILE
fi
fi
}
die() {
echo "$@" >&2
exit 1
}
#
# ACTION PROCESSING
#
error_not_implemented() {
echo "tuned: script function '$1' is not implemented." >&2
}
# implicit actions, will be used if not provided by profile script:
#
# * start must be implemented
# * stop must be implemented
start() {
error_not_implemented start
return 16
}
stop() {
error_not_implemented stop
return 16
}
#
# main processing
#
process() {
ARG="$1"
shift
case "$ARG" in
start)
start "$@"
RETVAL=$?
;;
stop)
stop "$@"
RETVAL=$?
;;
verify)
if declare -f verify &> /dev/null;
then
verify "$@"
else
:
fi
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|verify}"
RETVAL=2
;;
esac
exit $RETVAL
}