Login
Newsletter
Werbung

Sa, 15. Mai 2004, 00:00

Höhere Akkulaufzeiten durch Festplattenshutdown

Wer hat sich nicht schon mal gefragt, wie er die Festplatte in seinem Laptop mal länger als fünf Sekunden zum Schweigen bringen kann?

Von mschiff

Das Problem

Man möchte, dass die Festplatte in den Standby-Mode geht, wenn auf dem Rechner keine Aktivitäten stattfinden. Wenn man die Platte jedoch z.B. mit hdparm -y /dev/hda herunterfährt, startet sie meist wenige Sekunden später wieder. Auch ein Daemon wie z.B. noflushd, der die Platte nach einer bestimmten Idletime herunterfahren soll, kommt gar nicht zum Zug, da ständig kleinere Plattenaktivitäten stattfinden.

Schuld daran sind entweder User-Prozesse, die Platten I/O verursachen, und/oder bei Verwendung eines Journaling-Dateisystems das Schreiben des Journals auf die Platte (z.B. ext3 oder reiserfs). Und dann gibt es da z.B. noch den Kernel Update Daemon (kupdated) der alle fünf Sekunden »Dirty Data« auf die Platte schreibt.

All diese "Flush"-Zeiten lassen sich so tunen, dass die Platte sich eine größere Verschnaufpause gönnen kann.

Ein laptop_mode Patch von Jens Axboe, der im Kernel seit Version 2.4.23 enthalten ist, bewirkt zusätzlich noch, dass, sobald die Platte mal hochfährt, alle »Dirty buffers« auf die Platte geschrieben werden. Dabei schreibt Linux nicht nur die »Dirty buffers«, deren Zeit abgelaufen ist (expired), sondern alle, um Plattenzugriffe zu konzentrieren.

Mein System: Debian Sid mit eigenem Kernel 2.4.25, ACPI Daemon (acpid) und Platten-Shutdown Daemon (noflushd).

Umsetzung - das Laptop-Mode Skript

Das folgende Skript habe ich mir aus der Doku zum Laptop-Patch und der Anpassung an ext3 zusammengebaut und noch ergänzt. Mit ein wenig Anpassung für die VM-Tuning Parameter sollte es auch mit Kernel 2.6 funktionieren (siehe dieses Posting für Details).

Wichtig für mich war die zusätzliche mount-Option noatime. Ohne diese hatte das ganze Spiel bei mir nicht viel gebracht. Dieses Skript am besten in eine Datei /usr/local/sbin/laptop_mode speichern (chmod 755 /usr/local/sbin/laptop_mode nicht vergessen!)

Skript: laptop_mode

#!/bin/sh
# start or stop laptop mode, best run by a power management daemon when
# ac gets connected/disconnected from a laptop
#
# FIXME: assumes HZ == 100
# age time, in seconds. should be put into a sysconfig file
MAX_AGE=600
# kernel default dirty buffer age
DEF_AGE=30
DEF_UPDATE=5
if [ ! -w /proc/sys/vm/laptop_mode ]; then
 echo "Kernel is not patched with laptop_mode patch"
 exit 1
fi
parse_mount_opts () {
 OPT="$1"
 shift
 echo "$*" | \
 sed 's/.*/,&,/' | \
 sed 's/,'"$OPT"'=[0-9]*,/,/g' | \
 sed 's/,,*/,/g' | \
 sed 's/^,//' | \
 sed 's/,$//' | \
 cat -
}
case "$1" in
stop)
 # Now on AC power.
 U_AGE=$((100*$DEF_UPDATE))
 B_AGE=$((100*$DEF_AGE))
 echo -n "Stopping laptop mode"
 echo "0" > /proc/sys/vm/laptop_mode
 echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush
 cat /etc/mtab | \
 while read DEV MP FST OPTS DUMP PASS ; do
 case "$FST" in
 "ext3")
 PARSEDOPTS="$(parse_mount_opts commit $OPTS)"
 mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$DEF_UPDATE
 ;;
 "reiserfs")
 PARSEDOPTS="$(parse_mount_opts transaction $OPTS)"
 mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,transaction=$DEF_UPDATE
 ;;
 # No need to do anything for xfs
 esac
 done
 echo "."
;;
start)
 # Now off AC power.
 AGE=$((100*$MAX_AGE))
 echo -n "Starting laptop mode"
 echo "1" > /proc/sys/vm/laptop_mode
 echo "30 500 0 0 $AGE $AGE 60 20 0" > /proc/sys/vm/bdflush
 cat /etc/mtab | \
 while read DEV MP FST OPTS DUMP PASS ; do
 case "$FST" in
 "ext3")
 PARSEDOPTS="$(parse_mount_opts commit $OPTS)"
 mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE,noatime
 ;;
 "reiserfs")
 PARSEDOPTS="$(parse_mount_opts transaction $OPTS)"
 mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,transaction=$MAX_AGE,noatime
 ;;
 # No need to do anything for xfs
 esac
 done
 echo "."
;;
*)
 echo "Syntax: $(basename $0) "
;;
esac
exit 0

ACPI-Konfiguration

Damit der Laptopmode automatisch je nach Stromversorgung aktiviert oder deaktiviert wird, habe ich den acpid entsprechend konfiguriert. Dazu installiert man sich zwei weitere Dateien:

# /etc/acpid/events/ac
# This detects changes to AC power status, and passes them to
# /etc/acpi/ac.sh for further processing.
# Optionally you can specify the placeholder %e. It will pass
# through the whole kernel event message to the program you've
# specified.
event=ac_adapter
action=/etc/acpi/ac.sh

und:

#!/bin/sh
# /etc/acpid/ac.sh
# Detect loss of AC power and regaining of AC power, and take action
# appropriatly.
# On my laptop anyway, this script doesn't not get different parameters for
# loss of power and regained power. So, I have to use a separate program to
# tell what the adapter status is.
if on_ac_power; then
 # Now on AC power.
 /usr/local/sbin/laptop_mode stop
else
 # Now off AC power.
 /usr/local/sbin/laptop_mode start
fi
exit 0

(chmod 755 nicht vergessen) und startet den acpid neu (/etc/init.d/acpid restart).

Wenn die Platte immer noch oft wieder hochfährt, können da auch irgendwelche Prozesse im System daran Schuld sein, die Platten-I/O verursachen. Mit dem folgenden kleinen Skript kann man solchen Prozessen auf die Schliche kommen. Wichtig ist, dass klogd und syslogd vorher gestoppt werden. Die Befehle dazu können je nach Distribution variieren. Dieses Skript funktioniert unter Debian. Bitte mit Vorsicht benutzen.

#!/bin/sh
#
trap clean_exit 1 2 3 6 15
clean_exit () {
 echo 0 > /proc/sys/vm/block_dump
 /etc/init.d/sysklogd start
 echo "Adios"
 exit 0
}
/etc/init.d/sysklogd stop
echo 1 > /proc/sys/vm/block_dump
while true; do
 clear
 date
 dmesg | tail -n20
 sleep 1
done

noflushd

Darum, dass die Platte nach einer bestimmten Zeit auch heruntergefahren wird, kümmert sich noflushd. noflushd kann dazu benutzt werden, die Platten nach einer bstimmten Idle-Zeit abschalten zu lassen. Konfiguriert wird er unter Debian über die Datei /etc/default/noflushd. Hier sollte man die Variablen "TIMEOUT" und "DISKS" seinen Wünschen und seinem System entsprechend anpassen.

Anmerkungen: Mit diesen Einstellungen bleibt die Platte maximal zehn Minuten aus (600 Sekunden). Dieser Wert kann im laptop_mode Skript angepasst werden (MAX_AGE Variable).

Achtung: Im schlimmsten Fall können so auch natürlich die letzten zehn Minuten an Arbeit verlorengehen, wenn »Dirty Buffers« nicht auf die Platte geschrieben wurden und dann plötzlich unerwartet der Akku den Geist aufgibt. laptop_mode stop und das -Kommando sind kurz vor so einem Ereignis gute Freunde ;-)

Kommentare (Insgesamt: 0 )
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung