Added 'verify' shell function to the 'functions' API. This function is optional, if defined in the script, it is called during the verification. It's return code is checked. Function return code '0' means verification passed, other value means failure. Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
523 lines
12 KiB
Text
523 lines
12 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_SUFFIX=".save"
|
|
|
|
#
|
|
# Helpers
|
|
#
|
|
|
|
# Save value
|
|
# $0 STORAGE_NAME VALUE
|
|
save_value() {
|
|
[ "$#" -ne 2 ] && return
|
|
[ "$2" -a -e "${STORAGE}" ] && echo "$2" > "${STORAGE}/${1}${STORAGE_SUFFIX}"
|
|
}
|
|
|
|
# Save sysfs value
|
|
# $0 STORAGE_NAME SYSFS_NAME
|
|
save_sys() {
|
|
[ "$#" -ne 2 ] && return
|
|
[ -r "$2" -a ! -e "${STORAGE}/${1}${STORAGE_SUFFIX}" ] && cat "$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"
|
|
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
|
|
|
|
# prefer governor setting using cpuspeed daemon
|
|
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
|
|
|
|
service cpuspeed status &> /dev/null
|
|
[ $? -eq 3 ] && touch $CPUSPEED_STARTED || rm -f $CPUSPEED_STARTED
|
|
|
|
service cpuspeed restart &> /dev/null
|
|
|
|
# direct change using /sys fs
|
|
elif [ -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]; then
|
|
echo >&2
|
|
echo "Suggestion: install 'cpuspeed' package to get best tuning results." >&2
|
|
echo "Falling back to '$governor' scaling governor for all CPUs." >&2
|
|
echo >&2
|
|
|
|
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 [ -e $CPUSPEED_STARTED ]; then
|
|
rm -f $CPUSPEED_STARTED
|
|
service cpuspeed stop &> /dev/null
|
|
else
|
|
service cpuspeed restart &> /dev/null
|
|
fi
|
|
elif [ -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 $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
|
|
}
|
|
|
|
#
|
|
# 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() {
|
|
case "$1" 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
|
|
}
|