File: set_disk_settings

package info (click to toggle)
powersave 0.14.0-5
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 4,764 kB
  • ctags: 999
  • sloc: sh: 11,357; cpp: 8,103; ansic: 2,631; makefile: 388
file content (337 lines) | stat: -rwxr-xr-x 13,273 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
#!/bin/bash
###########################################################################
#                                                                         #
#                         Powersave Daemon                                #
#                                                                         #
#          Copyright (C) 2004,2005 SUSE Linux Products GmbH               #
#                                                                         #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the   #
# Free Software Foundation; either version 2 of the License, or (at you   #
# option) any later version.                                              #
#                                                                         #
# This program is distributed in the hope that it will be useful, but     #
# WITHOUT ANY WARRANTY; without even the implied warranty of              #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       #
# General Public License for more details.                                #
#                                                                         #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., #
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA                  #
#                                                                         #
#                                                                         #
# Authors Thomas Renninger (powersave@renninger.de)                       #
#         Stefan Seyfried (seife@suse.de)                                 #
#                                                                         #
###########################################################################
#
# This script is thought to be invoked by the powersave daemon
# It adjusts the machine to the settings of a specfic scheme

# At the moment only hard disk issues are managed by this script
# (e.g. setting standby/suspend timouts and acoustic settings),
# but there maybe added more in future.
# 

# where do we store if _we_ remounted a device?
STORE="/var/run/powersaved.remount"

# The script might take following parameters:
# 
# 1) The powersave daemon event that caused the script to be invoked 
# 2) The scheme which settings should be executed
#    Be careful. It is not the scheme name as specified in SCHEME_NAME
#    inside the scheme configuration file.
#    It is the name of the scheme configuration file, without leading path.
#    E.g. scheme_powersave should refer (by default) to the scheme configurations 
#    that are stored in /etc/sysconfig/powersave/scheme_powersave


# shameless rip from the laptop_mode script
# this part is inspired by the laptop_mode script from
# Jens Axboe, Kiko Piris, Bart Samwel, Dax Kelson which is in the
# Linux kernel Documentation/ directory
laptop_mode_func() {

    if [ ! -w /proc/sys/vm/laptop_mode ]; then
        DEBUG "Kernel is not patched with laptop_mode patch or not enough privileges." WARN
        return 1
    fi
    local AGE ACTIVE START
    local DEF_AGE DEF_UPDATE DEF_DIRTY_BACKGROUND_RATIO DEF_DIRTY_RATIO

    # kernel default dirty buffer age; no need to alter.
    DEF_AGE=30; DEF_UPDATE=5; DEF_DIRTY_BACKGROUND_RATIO=10; DEF_DIRTY_RATIO=40

    START=$1
    read ACTIVE < /proc/sys/vm/laptop_mode
    case "$START" in
        yes)
            if [ "$ACTIVE" -eq 0 ]; then
                AGE=$((100*$HD_MAX_AGE))
                DEBUG "Starting laptop_mode" DIAG
                echo "1"               > /proc/sys/vm/laptop_mode
                echo "$AGE"            > /proc/sys/vm/dirty_writeback_centisecs
                echo "$AGE"            > /proc/sys/vm/dirty_expire_centisecs
                echo "$HD_DIRTY_RATIO" > /proc/sys/vm/dirty_ratio
                echo "$HD_DIRTY_RATIO" > /proc/sys/vm/dirty_background_ratio
            else
                DEBUG "laptop_mode already active, ignoring" INFO
            fi
            ;;
        no)
            if [ "$ACTIVE" -eq 1 ]; then
                U_AGE=$((100*$DEF_UPDATE))
                B_AGE=$((100*$DEF_AGE))
                DEBUG "Stopping laptop_mode" DIAG
                echo "0"                           > /proc/sys/vm/laptop_mode
                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
            else
                DEBUG "laptop_mode already inactive, ignoring" DIAG
            fi
            ;;
        *)  DEBUG "invalid function call: laptop_mode_func '$START' '$REMOUNT'" ERROR
            return 1
            ;;
    esac
    return 0
}

#########################################################
# this function remounts filesystems with noatime and
# proper commit=XXX settings if necessary
do_remounts() {

    local DEV MP FST OPTS OLDOPTS DUMP PASS REMOUNT LINE

    REMOUNT=$1

    DEBUG "do remounts?: '$REMOUNT', set noatime: '$HD_NOATIME'" DIAG

    case $REMOUNT in
        yes)
            rm -f $STORE    # better safe than sorry.
            while read DEV MP FST OPTS DUMP PASS ; do
                OLDOPTS=$OPTS
                OPTS=${OPTS//commit=[0-9]*/}
                OPTS=${OPTS//,,/,}
                case "$FST" in
                    "ext3")
                        DEBUG "mount $DEV -t $FST $MP -o remount,$OPTS,commit=$HD_MAX_AGE" DIAG
                        mount $DEV -t $FST $MP -o remount,$OPTS,commit=$HD_MAX_AGE
                        echo "$DEV -t $FST $MP -o remount,$OLDOPTS" >> $STORE
                        ;;
                    "reiserfs")
                        [ "$HD_NOATIME" = "yes" ] && OPTS="$OPTS,noatime"
                        DEBUG "mount $DEV -t $FST $MP -o remount,$OPTS,commit=$HD_MAX_AGE" DIAG
                        mount $DEV -t $FST $MP -o remount,$OPTS,commit=$HD_MAX_AGE
                        echo "$DEV -t $FST $MP -o remount,$OLDOPTS" >> $STORE
                        ;;
                    "xfs")
                        DEBUG "mount $DEV -t $FST $MP -o remount,$OPTS" DIAG
                        mount $DEV -t $FST $MP -o remount,$OPTS
                        echo "$DEV -t $FST $MP -o remount,$OLDOPTS" >> $STORE
                        ;;
                esac
            done < /etc/mtab
            ;;
        no)
            if [ -f $STORE ]; then
                while read LINE; do
                    DEBUG "remounting with original options: 'mount $LINE'" DIAG
                    mount $LINE
                done < $STORE
                rm $STORE
            fi
            ;;
        *)  DEBUG "invalid function call: do_remounts '$REMOUNT'" ERROR
            return 1
            ;;
    esac
    return 0
}

#########################################################
# this function checks if the disk supports APM and AAM
# "return codes" are passed via global variables (ugly).
#
# FIXME: what about SATA disks? 
get_disk_aam_apm(){
    local DEV X
    declare -a X
    DISK_APM=false
    DISK_AAM=false
    DEV=$1  # the name of the device ("hda", "hdb", ...)
    [ -z "$DEV" ] && return 1
    X=(`cat /proc/ide/$DEV/identify`) || return 1 # this concatenates all lines...
    # ...and set ${X[0]}=word00, ${X[1]}=word01...
    # bit 9 of word 83 is AAM
    if [ $[0x${X[83]} & 0x0200 ] -ne 0 ] ; then
        DISK_AAM=true
    fi
    # bit 3 of word 83 is APM
    if [ $[0x${X[83]} & 0x08 ] -ne 0 ] ; then
        DISK_APM=true
    fi
}

# calls hdparm for all disks with the arguments given.
# arguments: 1. hdparm argument for AAM ('-M 128')
#            2. hdparm argument for APM ('-B 254')
#            3. raw hdparm arguments as provided by the user.
# 1 and 2 are only issued to disks that support them.
exec_hdparm() {
    local ARGS TYPE DEV DISKS DRIVE BUS
    local ACOU="$1"
    local STBY="$2"
    local  RAW="$3"
    local PROC="/proc/ide" # where to find all the IDE settings
    ARGS=""
    # Is this setting safe on all disks ?
    # we get the disks from HAL.
    DISKS=`hal-find-by-property --key storage.drive_type --string disk 2>&1`
    if [ $? -ne 0 ]; then
        DEBUG "could not retrieve list of disks from HAL: $DISKS" WARN
        return 0
    fi

    for DRIVE in $DISKS; do
        BUS=`hal-get-property --udi $DRIVE --key storage.bus`
        case $BUS in
            ide)
                DEV=`hal-get-property --udi $DRIVE --key block.device 2>&1`
                if [ $? -ne 0 ]; then
                    DEBUG "could not retrieve block device from HAL for udi '$DRIVE': $DEV" WARN
                    continue
                fi
                DEV=${DEV#/dev/}  # strip leading /dev/
                ############################################################
                # this case...esac can be taken out as soon as we know for #
                # sure that we do not get any false results from HAL.      #
                read TYPE < $PROC/$DEV/media
                case "$TYPE" in         # this should no longer be necessary with HAL.
                    disk)
                        DEBUG "We have a disk: /dev/$DEV" INFO
                        get_disk_aam_apm $DEV
                        $DISK_AAM && ARGS="$ARGS $ACOU" || \
                                DEBUG "  /dev/$DEV does not support AAM" DIAG
                        $DISK_APM && ARGS="$ARGS $STBY" || \
                                DEBUG "  /dev/$DEV does not support APM" DIAG
                        ARGS="$ARGS $RAW"
                        DEBUG "running /sbin/hdparm $ARGS /dev/$DEV" DIAG
                        /sbin/hdparm $ARGS /dev/$DEV &>/dev/null || \
                                DEBUG "hdparm returned error '$?'" WARN
                        ;;
                    *) 
                        DEBUG "This is not a disk: /dev/$DEV" WARN  # should never happen
                        ;;
                esac
                # take me out ASAP                                         #
                ############################################################
                ;;
            *)
                # other buses not handled yet...
                DEBUG "non-ide drive (udi='$DRIVE') ignored" DIAG
                ;;
        esac
    done
    return 0
}

execute_disk_settings() {
    # when changing from AC to DC and back....
    local LAPTOP ACOUSTIC STBY RAW REMOUNT
    local N # numeric dummy
    declare -i N
    # ATA spec says it is valid to set both, Advanced Power Management
    # and standby timeout value, which will set the disk to stanby
    # will be managed by disk
    # note that the values for those modes can be tuned in
    # /etc/sysconfig/powersave/disk
    LAPTOP=""; ACOUSTIC=""; STBY=""; RAW=""
    case "$DISK_STANDBY_MODE" in
        performance)
            N="$HDPARM_STBY_PERF"
            RAW="$HDPARM_RAW_PERF"
            REMOUNT="$HD_DO_REMOUNTS_PERF"
            LAPTOP="${HD_LAPTOP_MODE_PERF:-no}" ;;
        powersave)
            N="$HDPARM_STBY_SAVE"
            RAW="$HDPARM_RAW_SAVE"
            REMOUNT="$HD_DO_REMOUNTS_SAVE"
            LAPTOP="${HD_LAPTOP_MODE_SAVE:-no}" ;;
        aggressive_powersave|aggressiv_powersave)
            N="$HDPARM_STBY_AGGR"
            RAW="$HDPARM_RAW_AGGR"
            REMOUNT="$HD_DO_REMOUNTS_AGGR"
            LAPTOP="${HD_LAPTOP_MODE_AGGR:-yes}" ;;
        no|off)
            return 0 ;;
        *)
            DEBUG "unknown DISK_STANDBY_MODE 
                   Value: $DISK_STANDBY_MODE" ERROR
            return 1 ;;
    esac

    # if $HD_DO_REMOUNT_* is empty, fill in the value of $HD_LAPTOP_MODE_*
    REMOUNT=${REMOUNT:-$LAPTOP}

    [ $N -ne 0 ] && STBY="-B $N"

    N=0
    case "$DISK_ACOUSTIC" in
        performance)
            N="$HDPARM_ACOUSTIC_PERF" ;;
        low)
            N="$HDPARM_ACOUSTIC_LOW" ;;
        quiet)
            N="$HDPARM_ACOUSTIC_QUIET" ;;
        no|off)
            ;;
        *)
            DEBUG "unknown DISK_ACOUSTIC 
                   Value: '$DISK_ACOUSTIC'" ERROR ;;
    esac
    [ $N -ne 0 ] && ACOUSTIC="-M $N"

    [ -n "$LAPTOP" ] && laptop_mode_func $LAPTOP

    do_remounts $REMOUNT

    if [ -n "$ACOUSTIC" -o -n "$STBY" -o -n "$RAW" ]; then
        exec_hdparm "$ACOUSTIC" "$STBY" "$RAW"
    fi
    return 0
}

# first get helper functions (e.g. DEBUG, load_scheme, ...)
# this also sets EV_ID and traps for erroneous exit.
. "${0%/*}/helper_functions"

# get the config
. $SYSCONF_DIR/disk
# set the defaults. This is easier than changing all occurrences above
HD_MAX_AGE=${HD_MAX_AGE:-600}
HD_DIRTY_RATIO=${HD_DIRTY_RATIO:-75}

# then get scheme specific settings:
SCHEME_TO_EXECUTE=$2
if [ -n $SCHEME_TO_EXECUTE ];then
    load_scheme $SCHEME_TO_EXECUTE
else
    load_scheme
fi

if [ $? != 0 ]; then
    DEBUG "Could not execute scheme settings" ERROR
    $SCRIPT_RETURN $EV_ID 1 "execute_disk_settings finished"
    EXIT 1
fi

execute_disk_settings

$SCRIPT_RETURN $EV_ID 0 "execute_disk_settings finished"
EXIT 0