diff --git a/apmd.conf b/apmd.conf index 0a12ef3..ea6c641 100644 --- a/apmd.conf +++ b/apmd.conf @@ -102,7 +102,80 @@ LOWPOWER_SERVICES="atd crond" # value (e.g. "5s = Wait 5 seconds before allowing to suspend"). #DELAYSUSPEND="3s" -# If your machine supports using cpufreq to change its speed, you can enable -# this to support changing the cpu frequence to performance or powersave -# based on whether or not you are currently on AC power or battery power -#CPUFREQ="no" +# Laptop-mode configuration + +# Enable laptop mode +# possibly vale on, off +# Default: off +LAPTOPMODE="off" + +# Maximum time, in seconds, of hard drive spindown time that you are +# comfortable with. Worst case, it's possible that you could lose this +# amount of work if your battery fails you while in laptop mode. +#MAX_AGE=600 + +# Read-ahead, in 512-byte sectors. You can spin down the disk while playing MP3/OGG +# by setting the disk readahead to 8MB (READAHEAD=16384). Effectively, the disk +# will read a complete MP3 at once, and will then spin down while the MP3/OGG is +# playing. +#READAHEAD=4096 + +# Shall we remount journaled fs. with appropriate commit interval? (1=yes) +#DO_REMOUNTS=1 + +# And shall we add the "noatime" option to that as well? (1=yes) +#DO_REMOUNT_NOATIME=1 + +# Dirty synchronous ratio. At this percentage of dirty pages the process +# which +# calls write() does its own writeback +#DIRTY_RATIO=40 + +# +# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been +# exceeded, the kernel will wake pdflush which will then reduce the amount +# of dirty memory to dirty_background_ratio. Set this nice and low, so once +# some writeout has commenced, we do a lot of it. +# +#DIRTY_BACKGROUND_RATIO=5 + +# kernel default dirty buffer age +#DEF_AGE=30 +#DEF_UPDATE=5 +#DEF_DIRTY_BACKGROUND_RATIO=10 +#DEF_DIRTY_RATIO=40 +#DEF_XFS_AGE_BUFFER=15 +#DEF_XFS_SYNC_INTERVAL=30 +#DEF_XFS_BUFD_INTERVAL=1 + +# This must be adjusted manually to the value of HZ in the running kernel +# on 2.4, until the XFS people change their 2.4 external interfaces to work in +# centisecs. This can be automated, but it's a work in progress that still +# needs# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for +# external interfaces, and that is currently always set to 100. So you don't +# need to change this on 2.6. +#XFS_HZ=100 + +# Should the maximum CPU frequency be adjusted down while on battery? +# Requires CPUFreq to be setup. +# See Documentation/cpu-freq/user-guide.txt for more info +#DO_CPU=0 + +# When on battery what is the maximum CPU speed that the system should +# use? Legal values are "slowest" for the slowest speed that your +# CPU is able to operate at, or a value listed in: +# /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies +# Only applicable if DO_CPU=1. +#CPU_MAXFREQ=slowest + +# Idle timeout for your hard drive (man hdparm for valid values, -S option) +# Default is 2 hours on AC (AC_HD=244) and 20 seconds for battery (BATT_HD=4). +#AC_HD=244 +#BATT_HD=4 + +# The drives for which to adjust the idle timeout. Separate them by a space, +# e.g. HD="/dev/hda /dev/hdb". +#HD="/dev/hda" + +# Set the spindown timeout on a hard drive? +#DO_HD=1 diff --git a/apmd.init b/apmd.init index 51c496e..788da4a 100755 --- a/apmd.init +++ b/apmd.init @@ -8,12 +8,17 @@ # config: /etc/sysconfig/apmd # clock: /etc/sysconfig/clock -# If APM isn't supported by the kernel, try loading the module... -[ -e /proc/apm ] || /sbin/modprobe apm &>/dev/null - -# Don't bother if /proc/apm still doesn't exist, kernel doesn't have -# support for APM. -[ -e /proc/apm ] || exit 0 +### BEGIN INIT INFO +# Provides: apmd +# Required-Start: $syslog $local_fs +# Required-Stop: $syslog $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop apmd +# Description: apmd is used for monitoring battery status and logging it via +# syslog(8). It can also be used for shutting down the machine when +# the battery is low. +### END INIT INFO CONFIG=/etc/sysconfig/apmd @@ -23,8 +28,25 @@ CONFIG=/etc/sysconfig/apmd RETVAL=0 start() { + # Check that we're a priviledged user + [ `id -u` = 0 ] || exit 4 + + # If APM isn't supported by the kernel, try loading the module... + [ -e /proc/apm ] || /sbin/modprobe apm &>/dev/null + + # Don't bother if /proc/apm still doesn't exist, kernel doesn't have + # support for APM. + [ -e /proc/apm ] || exit 1 + + # Check if acpid is executable + [ -x /usr/sbin/apmd ] || exit 5 + + # Check if config exists + [ -f $CONFIG ] || exit 6 + + . "$CONFIG" + echo -n $"Starting up APM daemon: " - test -r "$CONFIG" && . "$CONFIG" daemon /usr/sbin/apmd -p $LOGPERCENTCHANGE -w $WARNPERCENT $ADDPARAMS \ -P /etc/sysconfig/apm-scripts/apmscript RETVAL=$? @@ -42,19 +64,11 @@ stop() { return $RETVAL } -dostatus() { - status apmd -} - restart() { stop start } -condrestart() { - [ -e /var/lock/subsys/apmd ] && restart || : -} - # See how we were called. case "$1" in start) @@ -64,17 +78,27 @@ case "$1" in stop ;; status) - dostatus + status apmd + RETVAL=$? ;; - restart|reload) + restart) restart ;; + reload) + restart + ;; + force-reload) + echo "$0: Unimplemented feature." + RETVAL=3 + ;; condrestart) - condrestart + if [ -f /var/lock/subsys/apmd ]; then + restart + fi ;; *) - echo $"Usage: apmd {start|stop|status|restart|reload|condrestart}" - exit 1 + echo $"Usage: apmd {start|stop|status|restart|reload|force-reload|condrestart}" + RETVAL=2 esac exit $RETVAL diff --git a/apmd.spec b/apmd.spec index 99ed055..d4a97be 100644 --- a/apmd.spec +++ b/apmd.spec @@ -1,11 +1,12 @@ Summary: Advanced Power Management (APM) BIOS utilities for laptops. Name: apmd Version: 3.2.2 -Release: 5 +Release: 6 Source: ftp://ftp.debian.org/debian/pool/main/a/apmd/%{name}_%{version}.orig.tar.gz Source1: apmd.init Source2: apmscript Source3: apmd.conf +Source4: laptopmode Patch: apmd-3.2-build.patch Patch1: apmd-3.2-umask.patch Patch2: apmd-3.2-error.patch @@ -59,6 +60,7 @@ install -m 644 apmsleep.fr.1 $RPM_BUILD_ROOT/%{_mandir}/fr/man1/ install -m 755 %{SOURCE1} $RPM_BUILD_ROOT/etc/rc.d/init.d/apmd install -m 755 %{SOURCE2} $RPM_BUILD_ROOT/etc/sysconfig/apm-scripts/ install -m 644 %{SOURCE3} $RPM_BUILD_ROOT/etc/sysconfig/apmd +install -m 755 %{SOURCE4} $RPM_BUILD_ROOT/etc/sysconfig/apm-scripts/ rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/apmd_proxy rm -rf $RPM_BUILD_ROOT%{_bindir}/on_ac_power rm -rf $RPM_BUILD_ROOT%{_libdir} $RPM_BUILD_ROOT%{_includedir} @@ -96,6 +98,14 @@ fi %config /etc/sysconfig/apm-scripts/* %changelog +* Wed Nov 07 2007 Zdenek Prikryl - 1:3.2.2-6 +- Update apmscript to use pccardctl (#192942) +- Update init script to comply with LSB standard (#237771) +- Fixed starting of anacron after resume (#83770) +- Fixed X_LOCK (#127318) +- Included laptopmode script (#91878) +- Fixed restarting network (#357381) + * Tue Aug 22 2006 Jesse Keating - 1:3.2.2-5 - Fix typos in apmscript (#194024) @@ -257,7 +267,7 @@ fi return to line power - Add maestro and cs4281 to the default SOUNDMODULES, they're quite common -* Thu Feb 15 2001 Trond Eivind Glomsr�d +* Thu Feb 15 2001 Trond Eivind Glomsrd - -change * Mon Feb 5 2001 Bernhard Rosenkraenzer @@ -346,42 +356,42 @@ fi * Mon Jun 19 2000 Bernhard Rosenkraenzer - FHSify -* Sat May 27 2000 Bernhard Rosenkr�nzer +* Sat May 27 2000 Bernhard Rosenkrnzer - Some more changes to apm-scripts: - Fix up HDPARM_AT_RESUME - Add ANACRON_ON_BATTERY, and default to turning it off -* Mon May 8 2000 Bernhard Rosenkr�nzer +* Mon May 8 2000 Bernhard Rosenkrnzer - Various fixes to the apm-scripts: - use modprobe instead of insmod for restoring sound - don't try to restore the X display if X isn't running - /usr/sbin/anacron, not /usr/bin/anacron - misc. cleanups -* Fri Feb 4 2000 Bernhard Rosenkr�nzer +* Fri Feb 4 2000 Bernhard Rosenkrnzer - rebuild to compress man pages -* Mon Jan 17 2000 Bernhard Rosenkr�nzer +* Mon Jan 17 2000 Bernhard Rosenkrnzer - Update to 3.0final -* Mon Jan 17 2000 Bernhard Rosenkr�nzer +* Mon Jan 17 2000 Bernhard Rosenkrnzer - Fixes for UTC clocks (Bug #7939) -* Thu Jan 6 2000 Bernhard Rosenkr�nzer +* Thu Jan 6 2000 Bernhard Rosenkrnzer - If anacron is installed, run it at resume time. -* Sun Nov 21 1999 Bernhard Rosenkr�nzer +* Sun Nov 21 1999 Bernhard Rosenkrnzer - Fix up the broken harddisk fix (needs to be done earlier during suspend, also we need to manually wake the drive at resume.) -* Sun Nov 21 1999 Bernhard Rosenkr�nzer +* Sun Nov 21 1999 Bernhard Rosenkrnzer - Updates to the apm-scripts and sysconfig/apmd: - Make hwclock --hctosys call optional (CLOCK_SYNC variable) - Add possibility to modify hdparm settings on suspend/resume. Some broken harddisks (Gericom 3xC) require this for suspend to disk to work. -* Wed Nov 10 1999 Bernhard Rosenkr�nzer +* Wed Nov 10 1999 Bernhard Rosenkrnzer - Put in new apm scripts to handle PCMCIA suspend/resume, and give the possibility to refresh displays and reload sound modules for some broken chipsets diff --git a/apmscript b/apmscript index 3b9add2..120b0d5 100755 --- a/apmscript +++ b/apmscript @@ -30,7 +30,7 @@ export NOLOCALE=1 [ -z "$CHANGEVT" ] && CHANGEVT="0" [ -z "$CLOCK_SYNC" ] && CLOCK_SYNC="no" [ -z "$CPUFREQ" ] && CPUFREQ="no" -if [ -n "`/sbin/pidof X`" ]; then +if [ -n "`/sbin/pidof X`" -o -n "`/sbin/pidof Xorg`" ]; then X_RUNNING=1 fi @@ -126,8 +126,8 @@ case "$PROG" in fi [ -n "$NEED_NETFS_START" ] && echo "/sbin/service netfs start" >>/var/run/apm-resume-post [ "$PCMCIARESTART" = "yes" ] && { - /sbin/cardctl suspend - /sbin/cardctl eject + /sbin/pccardctl suspend + /sbin/pccardctl eject } if [ "$PCMCIAWAIT" = "yes" ]; then until [ `LC_ALL=C grep "Socket .: empty" /var/lib/pcmcia/stab|wc -l` = `LC_ALL=C grep "Socket" /var/lib/pcmcia/stab|wc -l` ]; do @@ -148,20 +148,36 @@ case "$PROG" in [ "x$LOCK_X" = "xyes" -o "x$LOCK_X" = "x1" ] && { # Lock X, based on patch from Hannu Martikka # - w |tail +3 |awk '{print $1, $3}'| LC_ALL=C grep -v '-'| LC_ALL=C grep : | \ - sort -u | \ + # try to get user and display from utmp + users=`w |tail -n +3 |awk '{print $1, $2}'| LC_ALL=C grep -v '-'| LC_ALL=C grep : | sort -u` + # check if we found something + if [ -z $users ]; then + # get display + users=`ps ao args | LC_ALL=C grep -e 'bin/X[org]\?' | LC_ALL=C grep -v grep | LC_ALL=C sed 's_^.*\ \(:[0-9][\.[0-9]*]\?\ \).*$_\1_g'` + #get user, who is logged into system and ran xsession + users=`ps axfo user,args | LC_ALL=C grep -A 1 -e 'bin/X[org]\?' | LC_ALL=C grep -v grep | LC_ALL=C sed -e '/--/d' -e '/^.*X[org]\+.*$/d' | awk {'print $1'}`" "$users + fi + echo $users | \ while read line; do + echo $line > /tmp/apm3 Usern=`echo $line |awk '{print $1}'` XDisp=`echo $line |awk '{print $2}'` - if [ "x`/sbin/pidof 'kdeinit: kdesktop'`" != "x" ]; then + if [ "x`/sbin/pidof kdesktop`" != "x" ]; then # We're running KDE - a dcop call is sufficient. - su $Usern -c "DISPLAY=$XDisp dcop kdesktop KScreensaverIface 'lock()'" + su $Usern -c "(DISPLAY=$XDisp dcop kdesktop KScreensaverIface 'lock()' &)" + elif [ "x`/sbin/pidof gnome-screensaver`" != "x" ]; then + # We're running Gnome + P_GSS=`/sbin/pidof gnome-screensaver` + DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/$P_GSS/environ | sed 's/DBUS_SESSION_BUS_ADDRESS=//'` + su $Usern -c "(DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS gnome-screensaver-command --lock &)" else - # This isn't KDE... Do some ugly stuff. - if [ "x$Usern" = "xroot" ]; then - xlock -display $XDisp &>/dev/null & - else - su $Usern -c "xscreensaver-command -display $XDisp -lock || (xscreensaver -display $XDisp -no-splash &sleep 1; xscreensaver-command -display $XDisp -lock) || (xlock -display $XDisp &)" &>/dev/null + # Otherwise do some ugly stuff. + if [ -x /usr/bin/xscreensaver ]; then + # check if xscreensaver is running + [ -z "`/sbin/pidof xscreensaver`" ] && (su $Usern -c "xscreensaver -display $XDisp -no-splash &") && sleep 2 + su $Usern -c "(xscreensaver-command -display $XDisp -lock &)" &>/dev/null + elif [ -x /usr/bin/xlock ]; then + su $Usern -c "(xlock -display $XDisp &)" &>/dev/null fi fi done @@ -181,6 +197,12 @@ case "$PROG" in fi sync + RL=`runlevel | cut -d" " -f2`; + CROND=`/sbin/service crond status >/dev/null; [ $? -eq 0 ] && echo on || echo off` + ANACRON=`/sbin/chkconfig --list anacron | sed 's_^.*'$RL':\(on\|off\).*$_\1_g'` + + echo "$CROND $ANACRON" > /var/run/apm-resume-anacron + [ -f /etc/sysconfig/apm-scripts/apmcontinue ] && . /etc/sysconfig/apm-scripts/apmcontinue "$@" [ -e /var/run/apm-resume-post ] && chmod 0755 /var/run/apm-resume-post @@ -260,10 +282,12 @@ case "$PROG" in # Restore network and PCMCIA if [ "$PCMCIARESTART" = "yes" ] ; then - /sbin/cardctl insert - /sbin/cardctl resume + /sbin/pccardctl insert + /sbin/pccardctl resume fi + [ "$NET_RESTART" = "yes" ] && /sbin/service network start + [ "$NETFS_RESTART" = "yes" ] && /etc/rc.d/init.d/netfs start # Restart services if necessary @@ -281,21 +305,20 @@ case "$PROG" in # If anacron is installed and we're on AC power or we want # to run it even in battery mode. if [ -x /usr/sbin/anacron ]; then - if apm | LC_ALL=C grep -q on-line &>/dev/null; then - /usr/sbin/anacron -s - elif test "x$ANACRON_ON_BATTERY" = "xyes"; then - /usr/sbin/anacron -s + CROND=`cat /var/run/apm-resume-anacron | awk '{ print $1 }'` + ANACRON=`cat /var/run/apm-resume-anacron | awk '{ print $2 }'` + if [ "x$CROND" = "xon" -o "x$ANACRON" = "xon" ]; then + if apm | LC_ALL=C grep -q on-line &>/dev/null; then + /usr/sbin/anacron -s + elif test "x$ANACRON_ON_BATTERY" = "xyes"; then + /usr/sbin/anacron -s + fi + fi + if [ -f /var/run/apm-resume-anacron ]; then + rm -f /var/run/apm-resume-anacron fi fi - - if test "x$CPUFREQ" = "xyes"; then - if apm | LC_ALL=C grep -q on-line &>/dev/null; then - echo -n "0%100%100%performance" > /proc/cpufreq - else - echo -n "0%0%0%powersave" > /proc/cpufreq - fi - fi - + if test "x$HDPARM_AT_RESUME" != "x"; then for i in /proc/ide/hd*; do DRIVE=/dev/`echo $i |sed -e "s,.*/,,g"` @@ -311,19 +334,12 @@ case "$PROG" in [ -f /etc/sysconfig/apm-scripts/apmcontinue-pre ] && /etc/sysconfig/apm-scripts/apmcontinue-pre "$@" case $2 in power) - # change from performance to powersave or vice versa based - # on whether we're running on battery or ac power - if test "x$CPUFREQ" = "xyes"; then - if apm | LC_ALL=C grep -q on-line &>/dev/null; then - echo -n "0%100%100%performance" > /proc/cpufreq - else - echo -n "0%0%0%powersave" > /proc/cpufreq - fi - fi # Change from battery power to AC power or vice versa. if apm | LC_ALL=C grep -q on-line &>/dev/null; then - [ -f /proc/sys/vm/laptop_mode ] && echo 0 > /proc/sys/vm/laptop_mode + if [ "x$LAPTOPMODE" = "xyes" ]; then + /etc/sysconfig/apm-scripts/laptopmode stop + fi what="start" if [ -n "$LOWPOWER_SERVICES" -a -e /var/run/apmd/LOW_POWER ]; then rm -f /var/run/apmd/LOW_POWER @@ -333,7 +349,9 @@ case "$PROG" in fi else what="stop" - [ -f /proc/sys/vm/laptop_mode ] && echo 1 > /proc/sys/vm/laptop_mode + if [ "x$LAPTOPMODE" = "xyes" ]; then + /etc/sysconfig/apm-scripts/laptopmode start + fi fi if [ -n "$POWER_SERVICES" ]; then for i in $POWER_SERVICES; do diff --git a/laptopmode b/laptopmode new file mode 100755 index 0000000..a21335b --- /dev/null +++ b/laptopmode @@ -0,0 +1,376 @@ +#!/bin/bash +# +# Version for APM +# +# start or stop laptop_mode, best run by a power management daemon when +# ac gets connected/disconnected from a laptop +# +# +# Contributors to this script: Kiko Piris +# Bart Samwel +# Micha Feigin +# Andrew Morton +# Herve Eychenne +# Dax Kelson +# +# Original Linux 2.4 version by: Jens Axboe + +############################################################################# + +# Source config +if [ -f /etc/sysconfig/apmd ] ; then + . /etc/sysconfig/apmd +fi + +# Don't raise an error if the config file is incomplete +# set defaults instead: + +# Maximum time, in seconds, of hard drive spindown time that you are +# comfortable with. Worst case, it's possible that you could lose this +# amount of work if your battery fails you while in laptop mode. +MAX_AGE=${MAX_AGE:-'600'} + +# Read-ahead, in kilobytes +READAHEAD=${READAHEAD:-'4096'} + +# Shall we remount journaled fs. with appropriate commit interval? (1=yes) +DO_REMOUNTS=${DO_REMOUNTS:-'1'} + +# And shall we add the "noatime" option to that as well? (1=yes) +DO_REMOUNT_NOATIME=${DO_REMOUNT_NOATIME:-'1'} + +# Shall we adjust the idle timeout on a hard drive? +DO_HD=${DO_HD:-'1'} + +# Adjust idle timeout on which hard drive? +HD="${HD:-'/dev/hda'}" + +# spindown time for HD (hdparm -S values) +AC_HD=${AC_HD:-'244'} +BATT_HD=${BATT_HD:-'4'} + +# Dirty synchronous ratio. At this percentage of dirty pages the process which +# calls write() does its own writeback +DIRTY_RATIO=${DIRTY_RATIO:-'40'} + +# cpu frequency scaling +# See Documentation/cpu-freq/user-guide.txt for more info +DO_CPU=${CPU_MANAGE:-'0'} +CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'} + +# +# Allowed dirty background ratio, in percent. Once DIRTY_RATIO has been +# exceeded, the kernel will wake pdflush which will then reduce the amount +# of dirty memory to dirty_background_ratio. Set this nice and low, so once +# some writeout has commenced, we do a lot of it. +# +DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'} + +# kernel default dirty buffer age +DEF_AGE=${DEF_AGE:-'30'} +DEF_UPDATE=${DEF_UPDATE:-'5'} +DEF_DIRTY_BACKGROUND_RATIO=${DEF_DIRTY_BACKGROUND_RATIO:-'10'} +DEF_DIRTY_RATIO=${DEF_DIRTY_RATIO:-'40'} +DEF_XFS_AGE_BUFFER=${DEF_XFS_AGE_BUFFER:-'15'} +DEF_XFS_SYNC_INTERVAL=${DEF_XFS_SYNC_INTERVAL:-'30'} +DEF_XFS_BUFD_INTERVAL=${DEF_XFS_BUFD_INTERVAL:-'1'} + +# This must be adjusted manually to the value of HZ in the running kernel +# on 2.4, until the XFS people change their 2.4 external interfaces to work in +# centisecs. This can be automated, but it's a work in progress that still needs +# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for external +# interfaces, and that is currently always set to 100. So you don't need to +# change this on 2.6. +XFS_HZ=${XFS_HZ:-'100'} + +############################################################################# + +KLEVEL="$(uname -r | + { + IFS='.' read a b c + echo $a.$b + } +)" +case "$KLEVEL" in + "2.4"|"2.6") + ;; + *) + echo "Unhandled kernel version: $KLEVEL ('uname -r' = '$(uname -r)')" >&2 + exit 1 + ;; +esac + +if [ ! -e /proc/sys/vm/laptop_mode ] ; then + echo "Kernel is not patched with laptop_mode patch." >&2 + exit 1 +fi + +if [ ! -w /proc/sys/vm/laptop_mode ] ; then + echo "You do not have enough privileges to enable laptop_mode." >&2 + exit 1 +fi + +# Remove an option (the first parameter) of the form option= from +# a mount options string (the rest of the parameters). +parse_mount_opts () { + OPT="$1" + shift + echo ",$*," | sed \ + -e 's/,'"$OPT"'=[0-9]*,/,/g' \ + -e 's/,,*/,/g' \ + -e 's/^,//' \ + -e 's/,$//' +} + +# Remove an option (the first parameter) without any arguments from +# a mount option string (the rest of the parameters). +parse_nonumber_mount_opts () { + OPT="$1" + shift + echo ",$*," | sed \ + -e 's/,'"$OPT"',/,/g' \ + -e 's/,,*/,/g' \ + -e 's/^,//' \ + -e 's/,$//' +} + +# Find out the state of a yes/no option (e.g. "atime"/"noatime") in +# fstab for a given filesystem, and use this state to replace the +# value of the option in another mount options string. The device +# is the first argument, the option name the second, and the default +# value the third. The remainder is the mount options string. +# +# Example: +# parse_yesno_opts_wfstab /dev/hda1 atime atime defaults,noatime +# +# If fstab contains, say, "rw" for this filesystem, then the result +# will be "defaults,atime". +parse_yesno_opts_wfstab () { + L_DEV="$1" + OPT="$2" + DEF_OPT="$3" + shift 3 + L_OPTS="$*" + PARSEDOPTS1="$(parse_nonumber_mount_opts $OPT $L_OPTS)" + PARSEDOPTS1="$(parse_nonumber_mount_opts no$OPT $PARSEDOPTS1)" + # Watch for a default atime in fstab + FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)" + if echo "$FSTAB_OPTS" | grep "$OPT" > /dev/null ; then + # option specified in fstab: extract the value and use it + if echo "$FSTAB_OPTS" | grep "no$OPT" > /dev/null ; then + echo "$PARSEDOPTS1,no$OPT" + else + # no$OPT not found -- so we must have $OPT. + echo "$PARSEDOPTS1,$OPT" + fi + else + # option not specified in fstab -- choose the default. + echo "$PARSEDOPTS1,$DEF_OPT" + fi +} + +# Find out the state of a numbered option (e.g. "commit=NNN") in +# fstab for a given filesystem, and use this state to replace the +# value of the option in another mount options string. The device +# is the first argument, and the option name the second. The +# remainder is the mount options string in which the replacement +# must be done. +# +# Example: +# parse_mount_opts_wfstab /dev/hda1 commit defaults,commit=7 +# +# If fstab contains, say, "commit=3,rw" for this filesystem, then the +# result will be "rw,commit=3". +parse_mount_opts_wfstab () { + L_DEV="$1" + OPT="$2" + shift 2 + L_OPTS="$*" + PARSEDOPTS1="$(parse_mount_opts $OPT $L_OPTS)" + # Watch for a default commit in fstab + FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)" + if echo "$FSTAB_OPTS" | grep "$OPT=" > /dev/null ; then + # option specified in fstab: extract the value, and use it + echo -n "$PARSEDOPTS1,$OPT=" + echo ",$FSTAB_OPTS," | sed \ + -e 's/.*,'"$OPT"'=//' \ + -e 's/,.*//' + else + # option not specified in fstab: set it to 0 + echo "$PARSEDOPTS1,$OPT=0" + fi +} + +deduce_fstype () { + MP="$1" + # My root filesystem unfortunately has + # type "unknown" in /etc/mtab. If we encounter + # "unknown", we try to get the type from fstab. + cat /etc/fstab | + grep -v '^#' | + while read FSTAB_DEV FSTAB_MP FSTAB_FST FSTAB_OPTS FSTAB_DUMP FSTAB_DUMP ; do + if [ "$FSTAB_MP" = "$MP" ]; then + echo $FSTAB_FST + exit 0 + fi + done +} + +if [ $DO_REMOUNT_NOATIME -eq 1 ] ; then + NOATIME_OPT=",noatime" +fi + +case "$1" in + start) + AGE=$((100*$MAX_AGE)) + XFS_AGE=$(($XFS_HZ*$MAX_AGE)) + echo -n "Starting laptop_mode" + + if [ -d /proc/sys/vm/pagebuf ] ; then + # (For 2.4 and early 2.6.) + # This only needs to be set, not reset -- it is only used when + # laptop mode is enabled. + echo $XFS_AGE > /proc/sys/vm/pagebuf/lm_flush_age + echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval + elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then + # (A couple of early 2.6 laptop mode patches had these.) + # The same goes for these. + echo $XFS_AGE > /proc/sys/fs/xfs/lm_age_buffer + echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval + elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then + # (2.6.6) + # But not for these -- they are also used in normal + # operation. + echo $XFS_AGE > /proc/sys/fs/xfs/age_buffer + echo $XFS_AGE > /proc/sys/fs/xfs/sync_interval + elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then + # (2.6.7 upwards) + # And not for these either. These are in centisecs, + # not USER_HZ, so we have to use $AGE, not $XFS_AGE. + echo $AGE > /proc/sys/fs/xfs/age_buffer_centisecs + echo $AGE > /proc/sys/fs/xfs/xfssyncd_centisecs + echo 3000 > /proc/sys/fs/xfs/xfsbufd_centisecs + fi + + case "$KLEVEL" in + "2.4") + echo 1 > /proc/sys/vm/laptop_mode + echo "30 500 0 0 $AGE $AGE 60 20 0" > /proc/sys/vm/bdflush + ;; + "2.6") + echo 5 > /proc/sys/vm/laptop_mode + echo "$AGE" > /proc/sys/vm/dirty_writeback_centisecs + echo "$AGE" > /proc/sys/vm/dirty_expire_centisecs + echo "$DIRTY_RATIO" > /proc/sys/vm/dirty_ratio + echo "$DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio + ;; + esac + if [ $DO_REMOUNTS -eq 1 ]; then + cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do + PARSEDOPTS="$(parse_mount_opts "$OPTS")" + if [ "$FST" = 'unknown' ]; then + FST=$(deduce_fstype $MP) + fi + case "$FST" in + "ext3"|"reiserfs") + PARSEDOPTS="$(parse_mount_opts commit "$OPTS")" + mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE$NOATIME_OPT + ;; + "xfs") + mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT + ;; + esac + if [ -b $DEV ] ; then + blockdev --setra $(($READAHEAD * 2)) $DEV + fi + done + fi + if [ $DO_HD -eq 1 ] ; then + for THISHD in $HD ; do + /sbin/hdparm -S $BATT_HD $THISHD > /dev/null 2>&1 + /sbin/hdparm -B 1 $THISHD > /dev/null 2>&1 + done + fi + if [ $DO_CPU -eq 1 ]; then + for THISCPU in /sys/devices/system/cpu/*/; do + if [ -e $THISCPU/cpufreq/cpuinfo_min_freq ]; then + if [ $CPU_MAXFREQ = 'slowest' ]; then + CPU_MAXFREQ=`cat $THISCPU/cpufreq/cpuinfo_min_freq` + fi + echo $CPU_MAXFREQ > $THISCPU/cpufreq/scaling_max_freq + fi + done + fi + echo "." + ;; + stop) + U_AGE=$((100*$DEF_UPDATE)) + B_AGE=$((100*$DEF_AGE)) + echo -n "Stopping laptop_mode" + echo 0 > /proc/sys/vm/laptop_mode + if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then + # These need to be restored, if there are no lm_*. + echo $(($XFS_HZ*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer + echo $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/sync_interval + elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then + # These need to be restored as well. + echo $((100*$DEF_XFS_AGE_BUFFER)) > /proc/sys/fs/xfs/age_buffer_centisecs + echo $((100*$DEF_XFS_SYNC_INTERVAL)) > /proc/sys/fs/xfs/xfssyncd_centisecs + echo $((100*$DEF_XFS_BUFD_INTERVAL)) > /proc/sys/fs/xfs/xfsbufd_centisecs + fi + case "$KLEVEL" in + "2.4") + echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush + ;; + "2.6") + echo "$U_AGE" > /proc/sys/vm/dirty_writeback_centisecs + echo "$B_AGE" > /proc/sys/vm/dirty_expire_centisecs + echo "$DEF_DIRTY_RATIO" > /proc/sys/vm/dirty_ratio + echo "$DEF_DIRTY_BACKGROUND_RATIO" > /proc/sys/vm/dirty_background_ratio + ;; + esac + if [ $DO_REMOUNTS -eq 1 ] ; then + cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do + # Reset commit and atime options to defaults. + if [ "$FST" = 'unknown' ]; then + FST=$(deduce_fstype $MP) + fi + case "$FST" in + "ext3"|"reiserfs") + PARSEDOPTS="$(parse_mount_opts_wfstab $DEV commit $OPTS)" + PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $PARSEDOPTS)" + mount $DEV -t $FST $MP -o remount,$PARSEDOPTS + ;; + "xfs") + PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $OPTS)" + mount $DEV -t $FST $MP -o remount,$PARSEDOPTS + ;; + esac + if [ -b $DEV ] ; then + blockdev --setra 256 $DEV + fi + done + fi + if [ $DO_HD -eq 1 ] ; then + for THISHD in $HD ; do + /sbin/hdparm -S $AC_HD $THISHD > /dev/null 2>&1 + /sbin/hdparm -B 255 $THISHD > /dev/null 2>&1 + done + fi + if [ $DO_CPU -eq 1 ]; then + for THISCPU in /sys/devices/system/cpu/*/; do + if [ -e $THISCPU/cpufreq/cpuinfo_min_freq ]; then + echo `cat $THISCPU/cpufreq/cpuinfo_max_freq` > $THISCPU/cpufreq/scaling_max_freq + fi + done + fi + echo "." + ;; + *) + echo "Usage: $0 {start|stop}" 2>&1 + exit 1 + ;; + +esac + +exit 0