Rev 3 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
# vim: set syn=sh :
#
# This script contains functions which can be useful in ktune profile scripts.
#
#
# 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)"
# 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
}
DISK_READAHEAD_SAVE="/var/run/tuned/disk_readahead.save"
# usage: multiply_disk_readahead by
multiply_disk_readahead() {
by=$1
rm -f "$DISK_READAHEAD_SAVE"
# 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 "echo $old > $control" >> "$DISK_READAHEAD_SAVE" 2>/dev/null
(echo $new > $control) &>/dev/null
done
}
restore_disk_readahead() {
if [ -r "$DISK_READAHEAD_SAVE" ]; then
/bin/sh "$DISK_READAHEAD_SAVE" &>/dev/null
rm -f "$DISK_READAHEAD_SAVE"
fi
}
# usage: remount_disk options partition1 partition2 ...
remount_partitions() {
options=$1
shift
for partition in $@; do
mount -o remount,$options $partition
done
}
_devices_no_write_back_cache() {
for device in $@; do
grep -q "write back" /sys/block/"$device"/device/scsi_disk/*/cache_type 2>/dev/null && return 1
done
return 0
}
_disk_barriers_remount() {
mount_options="$1"
lsblk -lno TYPE,KNAME,MOUNTPOINT | \
awk '
{ type=$1; name=$2; mountpoint=$3; }
(type == "disk") {
device=name
next
}
(mountpoint ~ /^\// && mountpoint != "/" && mountpoint != "/boot") {
mountpoints[mountpoint] = mountpoints[mountpoint] " " device
}
END {
for (mountpoint in mountpoints) {
print mountpoint, mountpoints[mountpoint]
}
}
' | \
while read mountpoint devices; do
if _devices_no_write_back_cache $devices; then
mount -o remount,"$mount_options" "$mountpoint" >/dev/null 2>&1
fi
done
}
# remounts all non-root and non-boot partitions with nobarrier option
# SCSI drives with write back cache are skipped
disable_disk_barriers() {
_disk_barriers_remount nobarrier
}
# see: disable_disk_barriers
enable_disk_barriers() {
_disk_barriers_remount barrier
}
#
# CPU tuning
#
CPUSPEED_SAVE_FILE="/var/run/tuned/ktune-cpuspeed.save"
CPUSPEED_ORIG_GOV="/var/run/tuned/ktune-cpuspeed-governor-%s.save"
CPUSPEED_STARTED="/var/run/tuned/ktune-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/redhat_transparent_hugepage/enabled"
THP_SAVE="/var/run/tuned/ktune-thp.save"
[ -e "$THP_ENABLE" ] || THP_ENABLE="/sys/kernel/mm/transparent_hugepage/enabled"
set_transparent_hugepages() {
if [ -e $THP_ENABLE ]; then
cut -f2 -d'[' $THP_ENABLE | cut -f1 -d']' > $THP_SAVE
(echo "$1" > $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
#
_snd_ac97_powersave() {
value=$1
[ -e /sys/module/snd_ac97_codec/parameters/power_save ] && echo $value > /sys/module/snd_ac97_codec/parameters/power_save
}
enable_snd_ac97_powersave() {
_snd_ac97_powersave Y
}
disable_snd_ac97_powersave() {
_snd_ac97_powersave N
}
#
# CD DRIVES tuning
#
_cd_polling() {
[ "$1" == "1" ] && opts=--enable-polling || opts=
cddrives=$(command ls -1 /dev/scd* 2>/dev/null)
for i in $cddrives; do hal-disable-polling $opts --device $(readlink -f $i); done &>/dev/null
}
enable_cd_polling() {
_cd_polling 1
}
disable_cd_polling() {
_cd_polling 0
}
#
# SOFTWARE tuning
#
RSYSLOG_CFG="/etc/rsyslog.conf"
RSYSLOG_SAVE="/var/run/tuned/ktune-cpuspeed.save"
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
fi
}
eee_set_reduced_fsb() {
_eee_fsb_control 2
}
eee_set_normal_fsb() {
_eee_fsb_control 1
}
#
# KTUNE ACTION PROCESSING
#
error_not_implemented() {
echo "tuned: ktune 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
# * reload runs start
# * restart runs stop + start
# * status returns 0
start() {
error_not_implemented start
return 16
}
stop() {
error_not_implemented stop
return 16
}
reload() {
start
return $?
}
restart() {
stop && start
return $?
}
status() {
return 0
}
# main processing
process() {
VAR_SUBSYS_KTUNE="/var/lock/subsys/ktune"
case "$1" in
start)
[ -f "$VAR_SUBSYS_KTUNE" ] && exit 0
start
RETVAL=$?
;;
stop)
[ -f "$VAR_SUBSYS_KTUNE" ] || exit 0
stop
RETVAL=$?
;;
reload)
[ -f "$VAR_SUBSYS_KTUNE" ] && reload
RETVAL=$?
;;
restart|force-reload)
[ -f "$VAR_SUBSYS_KTUNE" ] && restart
RETVAL=$?
;;
condrestart|try-restart)
[ -f "$VAR_SUBSYS_KTUNE" ] || exit 0
restart
RETVAL=$?
;;
status)
status
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
RETVAL=2
;;
esac
exit $RETVAL
}