OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [Documentation/] [laptop-mode.txt] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
How to conserve battery power using laptop-mode
2
-----------------------------------------------
3
 
4
Document Author: Bart Samwel (bart@samwel.tk)
5
Date created: January 2, 2004
6
Last modified: December 06, 2004
7
 
8
Introduction
9
------------
10
 
11
Laptop mode is used to minimize the time that the hard disk needs to be spun up,
12
to conserve battery power on laptops. It has been reported to cause significant
13
power savings.
14
 
15
Contents
16
--------
17
 
18
* Introduction
19
* Installation
20
* Caveats
21
* The Details
22
* Tips & Tricks
23
* Control script
24
* ACPI integration
25
* Monitoring tool
26
 
27
 
28
Installation
29
------------
30
 
31
To use laptop mode, you don't need to set any kernel configuration options
32
or anything. Simply install all the files included in this document, and
33
laptop mode will automatically be started when you're on battery. For
34
your convenience, a tarball containing an installer can be downloaded at:
35
 
36
http://www.samwel.tk/laptop_mode/laptop_mode/
37
 
38
To configure laptop mode, you need to edit the configuration file, which is
39
located in /etc/default/laptop-mode on Debian-based systems, or in
40
/etc/sysconfig/laptop-mode on other systems.
41
 
42
Unfortunately, automatic enabling of laptop mode does not work for
43
laptops that don't have ACPI. On those laptops, you need to start laptop
44
mode manually. To start laptop mode, run "laptop_mode start", and to
45
stop it, run "laptop_mode stop". (Note: The laptop mode tools package now
46
has experimental support for APM, you might want to try that first.)
47
 
48
 
49
Caveats
50
-------
51
 
52
* The downside of laptop mode is that you have a chance of losing up to 10
53
  minutes of work. If you cannot afford this, don't use it! The supplied ACPI
54
  scripts automatically turn off laptop mode when the battery almost runs out,
55
  so that you won't lose any data at the end of your battery life.
56
 
57
* Most desktop hard drives have a very limited lifetime measured in spindown
58
  cycles, typically about 50.000 times (it's usually listed on the spec sheet).
59
  Check your drive's rating, and don't wear down your drive's lifetime if you
60
  don't need to.
61
 
62
* If you mount some of your ext3/reiserfs filesystems with the -n option, then
63
  the control script will not be able to remount them correctly. You must set
64
  DO_REMOUNTS=0 in the control script, otherwise it will remount them with the
65
  wrong options -- or it will fail because it cannot write to /etc/mtab.
66
 
67
* If you have your filesystems listed as type "auto" in fstab, like I did, then
68
  the control script will not recognize them as filesystems that need remounting.
69
  You must list the filesystems with their true type instead.
70
 
71
* It has been reported that some versions of the mutt mail client use file access
72
  times to determine whether a folder contains new mail. If you use mutt and
73
  experience this, you must disable the noatime remounting by setting the option
74
  DO_REMOUNT_NOATIME to 0 in the configuration file.
75
 
76
 
77
The Details
78
-----------
79
 
80
Laptop mode is controlled by the knob /proc/sys/vm/laptop_mode. This knob is
81
present for all kernels that have the laptop mode patch, regardless of any
82
configuration options. When the knob is set, any physical disk I/O (that might
83
have caused the hard disk to spin up) causes Linux to flush all dirty blocks. The
84
result of this is that after a disk has spun down, it will not be spun up
85
anymore to write dirty blocks, because those blocks had already been written
86
immediately after the most recent read operation. The value of the laptop_mode
87
knob determines the time between the occurrence of disk I/O and when the flush
88
is triggered. A sensible value for the knob is 5 seconds. Setting the knob to
89
 
90
 
91
To increase the effectiveness of the laptop_mode strategy, the laptop_mode
92
control script increases dirty_expire_centisecs and dirty_writeback_centisecs in
93
/proc/sys/vm to about 10 minutes (by default), which means that pages that are
94
dirtied are not forced to be written to disk as often. The control script also
95
changes the dirty background ratio, so that background writeback of dirty pages
96
is not done anymore. Combined with a higher commit value (also 10 minutes) for
97
ext3 or ReiserFS filesystems (also done automatically by the control script),
98
this results in concentration of disk activity in a small time interval which
99
occurs only once every 10 minutes, or whenever the disk is forced to spin up by
100
a cache miss. The disk can then be spun down in the periods of inactivity.
101
 
102
If you want to find out which process caused the disk to spin up, you can
103
gather information by setting the flag /proc/sys/vm/block_dump. When this flag
104
is set, Linux reports all disk read and write operations that take place, and
105
all block dirtyings done to files. This makes it possible to debug why a disk
106
needs to spin up, and to increase battery life even more. The output of
107
block_dump is written to the kernel output, and it can be retrieved using
108
"dmesg". When you use block_dump and your kernel logging level also includes
109
kernel debugging messages, you probably want to turn off klogd, otherwise
110
the output of block_dump will be logged, causing disk activity that is not
111
normally there.
112
 
113
 
114
Configuration
115
-------------
116
 
117
The laptop mode configuration file is located in /etc/default/laptop-mode on
118
Debian-based systems, or in /etc/sysconfig/laptop-mode on other systems. It
119
contains the following options:
120
 
121
MAX_AGE:
122
 
123
Maximum time, in seconds, of hard drive spindown time that you are
124
comfortable with. Worst case, it's possible that you could lose this
125
amount of work if your battery fails while you're in laptop mode.
126
 
127
MINIMUM_BATTERY_MINUTES:
128
 
129
Automatically disable laptop mode if the remaining number of minutes of
130
battery power is less than this value. Default is 10 minutes.
131
 
132
AC_HD/BATT_HD:
133
 
134
The idle timeout that should be set on your hard drive when laptop mode
135
is active (BATT_HD) and when it is not active (AC_HD). The defaults are
136
20 seconds (value 4) for BATT_HD  and 2 hours (value 244) for AC_HD. The
137
possible values are those listed in the manual page for "hdparm" for the
138
"-S" option.
139
 
140
HD:
141
 
142
The devices for which the spindown timeout should be adjusted by laptop mode.
143
Default is /dev/hda. If you specify multiple devices, separate them by a space.
144
 
145
READAHEAD:
146
 
147
Disk readahead, in 512-byte sectors, while laptop mode is active. A large
148
readahead can prevent disk accesses for things like executable pages (which are
149
loaded on demand while the application executes) and sequentially accessed data
150
(MP3s).
151
 
152
DO_REMOUNTS:
153
 
154
The control script automatically remounts any mounted journaled filesystems
155
with appropriate commit interval options. When this option is set to 0, this
156
feature is disabled.
157
 
158
DO_REMOUNT_NOATIME:
159
 
160
When remounting, should the filesystems be remounted with the noatime option?
161
Normally, this is set to "1" (enabled), but there may be programs that require
162
access time recording.
163
 
164
DIRTY_RATIO:
165
 
166
The percentage of memory that is allowed to contain "dirty" or unsaved data
167
before a writeback is forced, while laptop mode is active. Corresponds to
168
the /proc/sys/vm/dirty_ratio sysctl.
169
 
170
DIRTY_BACKGROUND_RATIO:
171
 
172
The percentage of memory that is allowed to contain "dirty" or unsaved data
173
after a forced writeback is done due to an exceeding of DIRTY_RATIO. Set
174
this nice and low. This corresponds to the /proc/sys/vm/dirty_background_ratio
175
sysctl.
176
 
177
Note that the behaviour of dirty_background_ratio is quite different
178
when laptop mode is active and when it isn't. When laptop mode is inactive,
179
dirty_background_ratio is the threshold percentage at which background writeouts
180
start taking place. When laptop mode is active, however, background writeouts
181
are disabled, and the dirty_background_ratio only determines how much writeback
182
is done when dirty_ratio is reached.
183
 
184
DO_CPU:
185
 
186
Enable CPU frequency scaling when in laptop mode. (Requires CPUFreq to be setup.
187
See Documentation/cpu-freq/user-guide.txt for more info. Disabled by default.)
188
 
189
CPU_MAXFREQ:
190
 
191
When on battery, what is the maximum CPU speed that the system should use? Legal
192
values are "slowest" for the slowest speed that your CPU is able to operate at,
193
or a value listed in /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies.
194
 
195
 
196
Tips & Tricks
197
-------------
198
 
199
* Bartek Kania reports getting up to 50 minutes of extra battery life (on top
200
  of his regular 3 to 3.5 hours) using a spindown time of 5 seconds (BATT_HD=1).
201
 
202
* You can spin down the disk while playing MP3, by setting disk readahead
203
  to 8MB (READAHEAD=16384). Effectively, the disk will read a complete MP3 at
204
  once, and will then spin down while the MP3 is playing. (Thanks to Bartek
205
  Kania.)
206
 
207
* Drew Scott Daniels observed: "I don't know why, but when I decrease the number
208
  of colours that my display uses it consumes less battery power. I've seen
209
  this on powerbooks too. I hope that this is a piece of information that
210
  might be useful to the Laptop Mode patch or it's users."
211
 
212
* In syslog.conf, you can prefix entries with a dash ``-'' to omit syncing the
213
  file after every logging. When you're using laptop-mode and your disk doesn't
214
  spin down, this is a likely culprit.
215
 
216
* Richard Atterer observed that laptop mode does not work well with noflushd
217
  (http://noflushd.sourceforge.net/), it seems that noflushd prevents laptop-mode
218
  from doing its thing.
219
 
220
* If you're worried about your data, you might want to consider using a USB
221
  memory stick or something like that as a "working area". (Be aware though
222
  that flash memory can only handle a limited number of writes, and overuse
223
  may wear out your memory stick pretty quickly. Do _not_ use journalling
224
  filesystems on flash memory sticks.)
225
 
226
 
227
Configuration file for control and ACPI battery scripts
228
-------------------------------------------------------
229
 
230
This allows the tunables to be changed for the scripts via an external
231
configuration file
232
 
233
It should be installed as /etc/default/laptop-mode on Debian, and as
234
/etc/sysconfig/laptop-mode on Red Hat, SUSE, Mandrake, and other work-alikes.
235
 
236
--------------------CONFIG FILE BEGIN-------------------------------------------
237
# Maximum time, in seconds, of hard drive spindown time that you are
238
# comfortable with. Worst case, it's possible that you could lose this
239
# amount of work if your battery fails you while in laptop mode.
240
#MAX_AGE=600
241
 
242
# Automatically disable laptop mode when the number of minutes of battery
243
# that you have left goes below this threshold.
244
MINIMUM_BATTERY_MINUTES=10
245
 
246
# Read-ahead, in 512-byte sectors. You can spin down the disk while playing MP3/OGG
247
# by setting the disk readahead to 8MB (READAHEAD=16384). Effectively, the disk
248
# will read a complete MP3 at once, and will then spin down while the MP3/OGG is
249
# playing.
250
#READAHEAD=4096
251
 
252
# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
253
#DO_REMOUNTS=1
254
 
255
# And shall we add the "noatime" option to that as well? (1=yes)
256
#DO_REMOUNT_NOATIME=1
257
 
258
# Dirty synchronous ratio.  At this percentage of dirty pages the process
259
# which
260
# calls write() does its own writeback
261
#DIRTY_RATIO=40
262
 
263
#
264
# Allowed dirty background ratio, in percent.  Once DIRTY_RATIO has been
265
# exceeded, the kernel will wake pdflush which will then reduce the amount
266
# of dirty memory to dirty_background_ratio.  Set this nice and low, so once
267
# some writeout has commenced, we do a lot of it.
268
#
269
#DIRTY_BACKGROUND_RATIO=5
270
 
271
# kernel default dirty buffer age
272
#DEF_AGE=30
273
#DEF_UPDATE=5
274
#DEF_DIRTY_BACKGROUND_RATIO=10
275
#DEF_DIRTY_RATIO=40
276
#DEF_XFS_AGE_BUFFER=15
277
#DEF_XFS_SYNC_INTERVAL=30
278
#DEF_XFS_BUFD_INTERVAL=1
279
 
280
# This must be adjusted manually to the value of HZ in the running kernel
281
# on 2.4, until the XFS people change their 2.4 external interfaces to work in
282
# centisecs. This can be automated, but it's a work in progress that still
283
# needs# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for
284
# external interfaces, and that is currently always set to 100. So you don't
285
# need to change this on 2.6.
286
#XFS_HZ=100
287
 
288
# Should the maximum CPU frequency be adjusted down while on battery?
289
# Requires CPUFreq to be setup.
290
# See Documentation/cpu-freq/user-guide.txt for more info
291
#DO_CPU=0
292
 
293
# When on battery what is the maximum CPU speed that the system should
294
# use? Legal values are "slowest" for the slowest speed that your
295
# CPU is able to operate at, or a value listed in:
296
# /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
297
# Only applicable if DO_CPU=1.
298
#CPU_MAXFREQ=slowest
299
 
300
# Idle timeout for your hard drive (man hdparm for valid values, -S option)
301
# Default is 2 hours on AC (AC_HD=244) and 20 seconds for battery (BATT_HD=4).
302
#AC_HD=244
303
#BATT_HD=4
304
 
305
# The drives for which to adjust the idle timeout. Separate them by a space,
306
# e.g. HD="/dev/hda /dev/hdb".
307
#HD="/dev/hda"
308
 
309
# Set the spindown timeout on a hard drive?
310
#DO_HD=1
311
 
312
--------------------CONFIG FILE END---------------------------------------------
313
 
314
 
315
Control script
316
--------------
317
 
318
Please note that this control script works for the Linux 2.4 and 2.6 series (thanks
319
to Kiko Piris).
320
 
321
--------------------CONTROL SCRIPT BEGIN----------------------------------------
322
#!/bin/bash
323
 
324
# start or stop laptop_mode, best run by a power management daemon when
325
# ac gets connected/disconnected from a laptop
326
#
327
# install as /sbin/laptop_mode
328
#
329
# Contributors to this script:   Kiko Piris
330
#                                Bart Samwel
331
#                                Micha Feigin
332
#                                Andrew Morton
333
#                                Herve Eychenne
334
#                                Dax Kelson
335
#
336
# Original Linux 2.4 version by: Jens Axboe
337
 
338
#############################################################################
339
 
340
# Source config
341
if [ -f /etc/default/laptop-mode ] ; then
342
        # Debian
343
        . /etc/default/laptop-mode
344
elif [ -f /etc/sysconfig/laptop-mode ] ; then
345
        # Others
346
        . /etc/sysconfig/laptop-mode
347
fi
348
 
349
# Don't raise an error if the config file is incomplete
350
# set defaults instead:
351
 
352
# Maximum time, in seconds, of hard drive spindown time that you are
353
# comfortable with. Worst case, it's possible that you could lose this
354
# amount of work if your battery fails you while in laptop mode.
355
MAX_AGE=${MAX_AGE:-'600'}
356
 
357
# Read-ahead, in kilobytes
358
READAHEAD=${READAHEAD:-'4096'}
359
 
360
# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
361
DO_REMOUNTS=${DO_REMOUNTS:-'1'}
362
 
363
# And shall we add the "noatime" option to that as well? (1=yes)
364
DO_REMOUNT_NOATIME=${DO_REMOUNT_NOATIME:-'1'}
365
 
366
# Shall we adjust the idle timeout on a hard drive?
367
DO_HD=${DO_HD:-'1'}
368
 
369
# Adjust idle timeout on which hard drive?
370
HD="${HD:-'/dev/hda'}"
371
 
372
# spindown time for HD (hdparm -S values)
373
AC_HD=${AC_HD:-'244'}
374
BATT_HD=${BATT_HD:-'4'}
375
 
376
# Dirty synchronous ratio.  At this percentage of dirty pages the process which
377
# calls write() does its own writeback
378
DIRTY_RATIO=${DIRTY_RATIO:-'40'}
379
 
380
# cpu frequency scaling
381
# See Documentation/cpu-freq/user-guide.txt for more info
382
DO_CPU=${CPU_MANAGE:-'0'}
383
CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'}
384
 
385
#
386
# Allowed dirty background ratio, in percent.  Once DIRTY_RATIO has been
387
# exceeded, the kernel will wake pdflush which will then reduce the amount
388
# of dirty memory to dirty_background_ratio.  Set this nice and low, so once
389
# some writeout has commenced, we do a lot of it.
390
#
391
DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'}
392
 
393
# kernel default dirty buffer age
394
DEF_AGE=${DEF_AGE:-'30'}
395
DEF_UPDATE=${DEF_UPDATE:-'5'}
396
DEF_DIRTY_BACKGROUND_RATIO=${DEF_DIRTY_BACKGROUND_RATIO:-'10'}
397
DEF_DIRTY_RATIO=${DEF_DIRTY_RATIO:-'40'}
398
DEF_XFS_AGE_BUFFER=${DEF_XFS_AGE_BUFFER:-'15'}
399
DEF_XFS_SYNC_INTERVAL=${DEF_XFS_SYNC_INTERVAL:-'30'}
400
DEF_XFS_BUFD_INTERVAL=${DEF_XFS_BUFD_INTERVAL:-'1'}
401
 
402
# This must be adjusted manually to the value of HZ in the running kernel
403
# on 2.4, until the XFS people change their 2.4 external interfaces to work in
404
# centisecs. This can be automated, but it's a work in progress that still needs
405
# some fixes. On 2.6 kernels, XFS uses USER_HZ instead of HZ for external
406
# interfaces, and that is currently always set to 100. So you don't need to
407
# change this on 2.6.
408
XFS_HZ=${XFS_HZ:-'100'}
409
 
410
#############################################################################
411
 
412
KLEVEL="$(uname -r |
413
             {
414
               IFS='.' read a b c
415
               echo $a.$b
416
             }
417
)"
418
case "$KLEVEL" in
419
        "2.4"|"2.6")
420
                ;;
421
        *)
422
                echo "Unhandled kernel version: $KLEVEL ('uname -r' = '$(uname -r)')" >&2
423
                exit 1
424
                ;;
425
esac
426
 
427
if [ ! -e /proc/sys/vm/laptop_mode ] ; then
428
        echo "Kernel is not patched with laptop_mode patch." >&2
429
        exit 1
430
fi
431
 
432
if [ ! -w /proc/sys/vm/laptop_mode ] ; then
433
        echo "You do not have enough privileges to enable laptop_mode." >&2
434
        exit 1
435
fi
436
 
437
# Remove an option (the first parameter) of the form option= from
438
# a mount options string (the rest of the parameters).
439
parse_mount_opts () {
440
        OPT="$1"
441
        shift
442
        echo ",$*," | sed               \
443
         -e 's/,'"$OPT"'=[0-9]*,/,/g'   \
444
         -e 's/,,*/,/g'                 \
445
         -e 's/^,//'                    \
446
         -e 's/,$//'
447
}
448
 
449
# Remove an option (the first parameter) without any arguments from
450
# a mount option string (the rest of the parameters).
451
parse_nonumber_mount_opts () {
452
        OPT="$1"
453
        shift
454
        echo ",$*," | sed               \
455
         -e 's/,'"$OPT"',/,/g'          \
456
         -e 's/,,*/,/g'                 \
457
         -e 's/^,//'                    \
458
         -e 's/,$//'
459
}
460
 
461
# Find out the state of a yes/no option (e.g. "atime"/"noatime") in
462
# fstab for a given filesystem, and use this state to replace the
463
# value of the option in another mount options string. The device
464
# is the first argument, the option name the second, and the default
465
# value the third. The remainder is the mount options string.
466
#
467
# Example:
468
# parse_yesno_opts_wfstab /dev/hda1 atime atime defaults,noatime
469
#
470
# If fstab contains, say, "rw" for this filesystem, then the result
471
# will be "defaults,atime".
472
parse_yesno_opts_wfstab () {
473
        L_DEV="$1"
474
        OPT="$2"
475
        DEF_OPT="$3"
476
        shift 3
477
        L_OPTS="$*"
478
        PARSEDOPTS1="$(parse_nonumber_mount_opts $OPT $L_OPTS)"
479
        PARSEDOPTS1="$(parse_nonumber_mount_opts no$OPT $PARSEDOPTS1)"
480
        # Watch for a default atime in fstab
481
        FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)"
482
        if echo "$FSTAB_OPTS" | grep "$OPT" > /dev/null ; then
483
                # option specified in fstab: extract the value and use it
484
                if echo "$FSTAB_OPTS" | grep "no$OPT" > /dev/null ; then
485
                        echo "$PARSEDOPTS1,no$OPT"
486
                else
487
                        # no$OPT not found -- so we must have $OPT.
488
                        echo "$PARSEDOPTS1,$OPT"
489
                fi
490
        else
491
                # option not specified in fstab -- choose the default.
492
                echo "$PARSEDOPTS1,$DEF_OPT"
493
        fi
494
}
495
 
496
# Find out the state of a numbered option (e.g. "commit=NNN") in
497
# fstab for a given filesystem, and use this state to replace the
498
# value of the option in another mount options string. The device
499
# is the first argument, and the option name the second. The
500
# remainder is the mount options string in which the replacement
501
# must be done.
502
#
503
# Example:
504
# parse_mount_opts_wfstab /dev/hda1 commit defaults,commit=7
505
#
506
# If fstab contains, say, "commit=3,rw" for this filesystem, then the
507
# result will be "rw,commit=3".
508
parse_mount_opts_wfstab () {
509
        L_DEV="$1"
510
        OPT="$2"
511
        shift 2
512
        L_OPTS="$*"
513
        PARSEDOPTS1="$(parse_mount_opts $OPT $L_OPTS)"
514
        # Watch for a default commit in fstab
515
        FSTAB_OPTS="$(awk '$1 == "'$L_DEV'" { print $4 }' /etc/fstab)"
516
        if echo "$FSTAB_OPTS" | grep "$OPT=" > /dev/null ; then
517
                # option specified in fstab: extract the value, and use it
518
                echo -n "$PARSEDOPTS1,$OPT="
519
                echo ",$FSTAB_OPTS," | sed \
520
                 -e 's/.*,'"$OPT"'=//'  \
521
                 -e 's/,.*//'
522
        else
523
                # option not specified in fstab: set it to 0
524
                echo "$PARSEDOPTS1,$OPT=0"
525
        fi
526
}
527
 
528
deduce_fstype () {
529
        MP="$1"
530
        # My root filesystem unfortunately has
531
        # type "unknown" in /etc/mtab. If we encounter
532
        # "unknown", we try to get the type from fstab.
533
        cat /etc/fstab |
534
        grep -v '^#' |
535
        while read FSTAB_DEV FSTAB_MP FSTAB_FST FSTAB_OPTS FSTAB_DUMP FSTAB_DUMP ; do
536
                if [ "$FSTAB_MP" = "$MP" ]; then
537
                        echo $FSTAB_FST
538
                        exit 0
539
                fi
540
        done
541
}
542
 
543
if [ $DO_REMOUNT_NOATIME -eq 1 ] ; then
544
        NOATIME_OPT=",noatime"
545
fi
546
 
547
case "$1" in
548
        start)
549
                AGE=$((100*$MAX_AGE))
550
                XFS_AGE=$(($XFS_HZ*$MAX_AGE))
551
                echo -n "Starting laptop_mode"
552
 
553
                if [ -d /proc/sys/vm/pagebuf ] ; then
554
                        # (For 2.4 and early 2.6.)
555
                        # This only needs to be set, not reset -- it is only used when
556
                        # laptop mode is enabled.
557
                        echo $XFS_AGE > /proc/sys/vm/pagebuf/lm_flush_age
558
                        echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval
559
                elif [ -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
560
                        # (A couple of early 2.6 laptop mode patches had these.)
561
                        # The same goes for these.
562
                        echo $XFS_AGE > /proc/sys/fs/xfs/lm_age_buffer
563
                        echo $XFS_AGE > /proc/sys/fs/xfs/lm_sync_interval
564
                elif [ -f /proc/sys/fs/xfs/age_buffer ] ; then
565
                        # (2.6.6)
566
                        # But not for these -- they are also used in normal
567
                        # operation.
568
                        echo $XFS_AGE > /proc/sys/fs/xfs/age_buffer
569
                        echo $XFS_AGE > /proc/sys/fs/xfs/sync_interval
570
                elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
571
                        # (2.6.7 upwards)
572
                        # And not for these either. These are in centisecs,
573
                        # not USER_HZ, so we have to use $AGE, not $XFS_AGE.
574
                        echo $AGE > /proc/sys/fs/xfs/age_buffer_centisecs
575
                        echo $AGE > /proc/sys/fs/xfs/xfssyncd_centisecs
576
                        echo 3000 > /proc/sys/fs/xfs/xfsbufd_centisecs
577
                fi
578
 
579
                case "$KLEVEL" in
580
                        "2.4")
581
                                echo 1                                  > /proc/sys/vm/laptop_mode
582
                                echo "30 500 0 0 $AGE $AGE 60 20 0"     > /proc/sys/vm/bdflush
583
                                ;;
584
                        "2.6")
585
                                echo 5                                  > /proc/sys/vm/laptop_mode
586
                                echo "$AGE"                             > /proc/sys/vm/dirty_writeback_centisecs
587
                                echo "$AGE"                             > /proc/sys/vm/dirty_expire_centisecs
588
                                echo "$DIRTY_RATIO"                     > /proc/sys/vm/dirty_ratio
589
                                echo "$DIRTY_BACKGROUND_RATIO"          > /proc/sys/vm/dirty_background_ratio
590
                                ;;
591
                esac
592
                if [ $DO_REMOUNTS -eq 1 ]; then
593
                        cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
594
                                PARSEDOPTS="$(parse_mount_opts "$OPTS")"
595
                                if [ "$FST" = 'unknown' ]; then
596
                                        FST=$(deduce_fstype $MP)
597
                                fi
598
                                case "$FST" in
599
                                        "ext3"|"reiserfs")
600
                                                PARSEDOPTS="$(parse_mount_opts commit "$OPTS")"
601
                                                mount $DEV -t $FST $MP -o remount,$PARSEDOPTS,commit=$MAX_AGE$NOATIME_OPT
602
                                                ;;
603
                                        "xfs")
604
                                                mount $DEV -t $FST $MP -o remount,$OPTS$NOATIME_OPT
605
                                                ;;
606
                                esac
607
                                if [ -b $DEV ] ; then
608
                                        blockdev --setra $(($READAHEAD * 2)) $DEV
609
                                fi
610
                        done
611
                fi
612
                if [ $DO_HD -eq 1 ] ; then
613
                        for THISHD in $HD ; do
614
                                /sbin/hdparm -S $BATT_HD $THISHD > /dev/null 2>&1
615
                                /sbin/hdparm -B 1 $THISHD > /dev/null 2>&1
616
                        done
617
                fi
618
                if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then
619
                        if [ $CPU_MAXFREQ = 'slowest' ]; then
620
                                CPU_MAXFREQ=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`
621
                        fi
622
                        echo $CPU_MAXFREQ > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
623
                fi
624
                echo "."
625
                ;;
626
        stop)
627
                U_AGE=$((100*$DEF_UPDATE))
628
                B_AGE=$((100*$DEF_AGE))
629
                echo -n "Stopping laptop_mode"
630
                echo 0 > /proc/sys/vm/laptop_mode
631
                if [ -f /proc/sys/fs/xfs/age_buffer -a ! -f /proc/sys/fs/xfs/lm_age_buffer ] ; then
632
                        # These need to be restored, if there are no lm_*.
633
                        echo $(($XFS_HZ*$DEF_XFS_AGE_BUFFER))           > /proc/sys/fs/xfs/age_buffer
634
                        echo $(($XFS_HZ*$DEF_XFS_SYNC_INTERVAL))        > /proc/sys/fs/xfs/sync_interval
635
                elif [ -f /proc/sys/fs/xfs/age_buffer_centisecs ] ; then
636
                        # These need to be restored as well.
637
                        echo $((100*$DEF_XFS_AGE_BUFFER))       > /proc/sys/fs/xfs/age_buffer_centisecs
638
                        echo $((100*$DEF_XFS_SYNC_INTERVAL))    > /proc/sys/fs/xfs/xfssyncd_centisecs
639
                        echo $((100*$DEF_XFS_BUFD_INTERVAL))    > /proc/sys/fs/xfs/xfsbufd_centisecs
640
                fi
641
                case "$KLEVEL" in
642
                        "2.4")
643
                                echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush
644
                                ;;
645
                        "2.6")
646
                                echo "$U_AGE"                           > /proc/sys/vm/dirty_writeback_centisecs
647
                                echo "$B_AGE"                           > /proc/sys/vm/dirty_expire_centisecs
648
                                echo "$DEF_DIRTY_RATIO"                 > /proc/sys/vm/dirty_ratio
649
                                echo "$DEF_DIRTY_BACKGROUND_RATIO"      > /proc/sys/vm/dirty_background_ratio
650
                                ;;
651
                esac
652
                if [ $DO_REMOUNTS -eq 1 ] ; then
653
                        cat /etc/mtab | while read DEV MP FST OPTS DUMP PASS ; do
654
                                # Reset commit and atime options to defaults.
655
                                if [ "$FST" = 'unknown' ]; then
656
                                        FST=$(deduce_fstype $MP)
657
                                fi
658
                                case "$FST" in
659
                                        "ext3"|"reiserfs")
660
                                                PARSEDOPTS="$(parse_mount_opts_wfstab $DEV commit $OPTS)"
661
                                                PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $PARSEDOPTS)"
662
                                                mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
663
                                                ;;
664
                                        "xfs")
665
                                                PARSEDOPTS="$(parse_yesno_opts_wfstab $DEV atime atime $OPTS)"
666
                                                mount $DEV -t $FST $MP -o remount,$PARSEDOPTS
667
                                                ;;
668
                                esac
669
                                if [ -b $DEV ] ; then
670
                                        blockdev --setra 256 $DEV
671
                                fi
672
                        done
673
                fi
674
                if [ $DO_HD -eq 1 ] ; then
675
                        for THISHD in $HD ; do
676
                                /sbin/hdparm -S $AC_HD $THISHD > /dev/null 2>&1
677
                                /sbin/hdparm -B 255 $THISHD > /dev/null 2>&1
678
                        done
679
                fi
680
                if [ $DO_CPU -eq 1 -a -e /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq ]; then
681
                        echo `cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq` > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
682
                fi
683
                echo "."
684
                ;;
685
        *)
686
                echo "Usage: $0 {start|stop}" 2>&1
687
                exit 1
688
                ;;
689
 
690
esac
691
 
692
exit 0
693
--------------------CONTROL SCRIPT END------------------------------------------
694
 
695
 
696
ACPI integration
697
----------------
698
 
699
Dax Kelson submitted this so that the ACPI acpid daemon will
700
kick off the laptop_mode script and run hdparm. The part that
701
automatically disables laptop mode when the battery is low was
702
written by Jan Topinski.
703
 
704
-----------------/etc/acpi/events/ac_adapter BEGIN------------------------------
705
event=ac_adapter
706
action=/etc/acpi/actions/ac.sh %e
707
----------------/etc/acpi/events/ac_adapter END---------------------------------
708
 
709
 
710
-----------------/etc/acpi/events/battery BEGIN---------------------------------
711
event=battery.*
712
action=/etc/acpi/actions/battery.sh %e
713
----------------/etc/acpi/events/battery END------------------------------------
714
 
715
 
716
----------------/etc/acpi/actions/ac.sh BEGIN-----------------------------------
717
#!/bin/bash
718
 
719
# ac on/offline event handler
720
 
721
status=`awk '/^state: / { print $2 }' /proc/acpi/ac_adapter/$2/state`
722
 
723
case $status in
724
        "on-line")
725
                /sbin/laptop_mode stop
726
                exit 0
727
        ;;
728
        "off-line")
729
                /sbin/laptop_mode start
730
                exit 0
731
        ;;
732
esac
733
---------------------------/etc/acpi/actions/ac.sh END--------------------------
734
 
735
 
736
---------------------------/etc/acpi/actions/battery.sh BEGIN-------------------
737
#! /bin/bash
738
 
739
# Automatically disable laptop mode when the battery almost runs out.
740
 
741
BATT_INFO=/proc/acpi/battery/$2/state
742
 
743
if [[ -f /proc/sys/vm/laptop_mode ]]
744
then
745
   LM=`cat /proc/sys/vm/laptop_mode`
746
   if [[ $LM -gt 0 ]]
747
   then
748
     if [[ -f $BATT_INFO ]]
749
     then
750
        # Source the config file only now that we know we need
751
        if [ -f /etc/default/laptop-mode ] ; then
752
                # Debian
753
                . /etc/default/laptop-mode
754
        elif [ -f /etc/sysconfig/laptop-mode ] ; then
755
                # Others
756
                . /etc/sysconfig/laptop-mode
757
        fi
758
        MINIMUM_BATTERY_MINUTES=${MINIMUM_BATTERY_MINUTES:-'10'}
759
 
760
        ACTION="`cat $BATT_INFO | grep charging | cut -c 26-`"
761
        if [[ ACTION -eq "discharging" ]]
762
        then
763
           PRESENT_RATE=`cat $BATT_INFO | grep "present rate:" | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
764
           REMAINING=`cat $BATT_INFO | grep "remaining capacity:" | sed  "s/.* \([0-9][0-9]* \).*/\1/" `
765
        fi
766
        if (($REMAINING * 60 / $PRESENT_RATE < $MINIMUM_BATTERY_MINUTES))
767
        then
768
           /sbin/laptop_mode stop
769
        fi
770
     else
771
       logger -p daemon.warning "You are using laptop mode and your battery interface $BATT_INFO is missing. This may lead to loss of data when the battery runs out. Check kernel ACPI support and /proc/acpi/battery folder, and edit /etc/acpi/battery.sh to set BATT_INFO to the correct path."
772
     fi
773
   fi
774
fi
775
---------------------------/etc/acpi/actions/battery.sh END--------------------
776
 
777
 
778
Monitoring tool
779
---------------
780
 
781
Bartek Kania submitted this, it can be used to measure how much time your disk
782
spends spun up/down.
783
 
784
---------------------------dslm.c BEGIN-----------------------------------------
785
/*
786
 * Simple Disk Sleep Monitor
787
 *  by Bartek Kania
788
 * Licenced under the GPL
789
 */
790
#include 
791
#include 
792
#include 
793
#include 
794
#include 
795
#include 
796
#include 
797
#include 
798
#include 
799
#include 
800
 
801
#ifdef DEBUG
802
#define D(x) x
803
#else
804
#define D(x)
805
#endif
806
 
807
int endit = 0;
808
 
809
/* Check if the disk is in powersave-mode
810
 * Most of the code is stolen from hdparm.
811
 * 1 = active, 0 = standby/sleep, -1 = unknown */
812
int check_powermode(int fd)
813
{
814
    unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
815
    int state;
816
 
817
    if (ioctl(fd, HDIO_DRIVE_CMD, &args)
818
        && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
819
        && ioctl(fd, HDIO_DRIVE_CMD, &args)) {
820
        if (errno != EIO || args[0] != 0 || args[1] != 0) {
821
            state = -1; /* "unknown"; */
822
        } else
823
            state = 0; /* "sleeping"; */
824
    } else {
825
        state = (args[2] == 255) ? 1 : 0;
826
    }
827
    D(printf(" drive state is:  %d\n", state));
828
 
829
    return state;
830
}
831
 
832
char *state_name(int i)
833
{
834
    if (i == -1) return "unknown";
835
    if (i == 0) return "sleeping";
836
    if (i == 1) return "active";
837
 
838
    return "internal error";
839
}
840
 
841
char *myctime(time_t time)
842
{
843
    char *ts = ctime(&time);
844
    ts[strlen(ts) - 1] = 0;
845
 
846
    return ts;
847
}
848
 
849
void measure(int fd)
850
{
851
    time_t start_time;
852
    int last_state;
853
    time_t last_time;
854
    int curr_state;
855
    time_t curr_time = 0;
856
    time_t time_diff;
857
    time_t active_time = 0;
858
    time_t sleep_time = 0;
859
    time_t unknown_time = 0;
860
    time_t total_time = 0;
861
    int changes = 0;
862
    float tmp;
863
 
864
    printf("Starting measurements\n");
865
 
866
    last_state = check_powermode(fd);
867
    start_time = last_time = time(0);
868
    printf("  System is in state %s\n\n", state_name(last_state));
869
 
870
    while(!endit) {
871
        sleep(1);
872
        curr_state = check_powermode(fd);
873
 
874
        if (curr_state != last_state || endit) {
875
            changes++;
876
            curr_time = time(0);
877
            time_diff = curr_time - last_time;
878
 
879
            if (last_state == 1) active_time += time_diff;
880
            else if (last_state == 0) sleep_time += time_diff;
881
            else unknown_time += time_diff;
882
 
883
            last_state = curr_state;
884
            last_time = curr_time;
885
 
886
            printf("%s: State-change to %s\n", myctime(curr_time),
887
                   state_name(curr_state));
888
        }
889
    }
890
    changes--; /* Compensate for SIGINT */
891
 
892
    total_time = time(0) - start_time;
893
    printf("\nTotal running time:  %lus\n", curr_time - start_time);
894
    printf(" State changed %d times\n", changes);
895
 
896
    tmp = (float)sleep_time / (float)total_time * 100;
897
    printf(" Time in sleep state:   %lus (%.2f%%)\n", sleep_time, tmp);
898
    tmp = (float)active_time / (float)total_time * 100;
899
    printf(" Time in active state:  %lus (%.2f%%)\n", active_time, tmp);
900
    tmp = (float)unknown_time / (float)total_time * 100;
901
    printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
902
}
903
 
904
void ender(int s)
905
{
906
    endit = 1;
907
}
908
 
909
void usage()
910
{
911
    puts("usage: dslm [-w 
912
    exit(0);
913
}
914
 
915
int main(int argc, char **argv)
916
{
917
    int fd;
918
    char *disk = 0;
919
    int settle_time = 60;
920
 
921
    /* Parse the simple command-line */
922
    if (argc == 2)
923
        disk = argv[1];
924
    else if (argc == 4) {
925
        settle_time = atoi(argv[2]);
926
        disk = argv[3];
927
    } else
928
        usage();
929
 
930
    if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
931
        printf("Can't open %s, because: %s\n", disk, strerror(errno));
932
        exit(-1);
933
    }
934
 
935
    if (settle_time) {
936
        printf("Waiting %d seconds for the system to settle down to "
937
               "'normal'\n", settle_time);
938
        sleep(settle_time);
939
    } else
940
        puts("Not waiting for system to settle down");
941
 
942
    signal(SIGINT, ender);
943
 
944
    measure(fd);
945
 
946
    close(fd);
947
 
948
    return 0;
949
}
950
---------------------------dslm.c END-------------------------------------------

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.