File: prepare_suspend_to_disk

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 (279 lines) | stat: -rwxr-xr-x 11,733 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
#!/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                  #
#                                                                         #
###########################################################################
#
# first get helper functions (e.g. DEBUG, load_scheme, ...)
. "${0%/*}/helper_functions"
. "${PUB_SCRIPT_DIR}/sleep_helper_functions"
. "${PUB_SCRIPT_DIR}/sleep_helper_messages"

set_variables "suspend2disk"
prepare_logs  "suspend2disk"
declare -i PERCENT
export PERCENT=0    # ugly global variable, but the easiest way to go.
export STEP=5

##EV_ID="$4" # event id, needed for SCRIPT_RETURN, set in helper_functions

progress ""

#############################################################################
# if the system is configured for 855resolution, we _must_ switch away from
# X before suspend
if [ -e /etc/sysconfig/videobios ]; then
    . /etc/sysconfig/videobios
    if [ "$VIDEOBIOS_PATCH" = "yes" ]; then
        SWITCH_VT=yes
        echo "VIDEOBIOS_PATCH is enabled" >> $LSMOD_LOG
    fi
fi

#############################################################################
# try to find a kernel image that matches the actually running kernel.
# We need this, if more than one kernel is installed. This works reasonably
# well with grub, if all kernels are named "vmlinuz-`uname -r`" and are
# located in /boot. If they are not, good luck ;-)

declare -a KERNELS MENU_ENTRIES
declare -i DEFAULT_BOOT
eval `get_kernels`  # works only with grub, but we have no other
                    # choice anyway for now.
NEXT_BOOT=""
RUNNING=`uname -r`
ARCH=`uname -m`
let PERCENT+=$STEP
if [ "${BOOT_LOADER:-GRUB}" == "GRUB" ]; then
    progress "${_M01}"
    declare -i I=0
    DEBUG "running kernel: $RUNNING" DIAG
    while [ -n "${KERNELS[$I]}" ]; do
        BOOTING="${KERNELS[$I]}"
        if IMAGE=`readlink /boot/$BOOTING` && [ -e "/boot/${IMAGE##*/}" ]; then
            DEBUG "Found kernel symlink $BOOTING => $IMAGE" INFO
            BOOTING=$IMAGE
        fi
        case $ARCH in
            ppc*)   BOOTING="${BOOTING#*vmlinux-}" ;;
            *)      BOOTING="${BOOTING#*vmlinuz-}" ;;
        esac
        if [ "$RUNNING" == "$BOOTING" ]; then
            NEXT_BOOT=${MENU_ENTRIES[$I]}
            DEBUG "running kernel corresponds to grub menu entry $NEXT_BOOT" DIAG
            DEBUG "kernel filename: '${KERNELS[$I]}'" DIAG
            echo "running kernel is grub menu entry $NEXT_BOOT (${KERNELS[$I]})" >> $LSMOD_LOG
            break
        fi
        let I++
    done
    # if we have not found a kernel, issue a warning.
    # if we have found a kernel, we'll do "grub-once" later, after
    # prepare_suspend finished.
    if [ -z "$NEXT_BOOT" ]; then
        DEBUG "no kernelfile matching the running kernel found" WARN
        echo "no kernelfile matching the running kernel found" >> $LSMOD_LOG
    fi
else
    echo "BOOT_LOADER != GRUB, no kernel selection for next boot." >> $LSMOD_LOG
fi

let PERCENT+=$STEP
progress "${_M01}"

#############################################################################
# if we did not find a kernel (or BOOT_LOADER is not GRUB) check,
# if the running kernel is still the one that will (probably) be booted for
# resume (default entry in menu.lst or if there is none the kernel file
# /boot/vmlinuz points to.)
# This will only work, if you use "original" SUSE kernels.
# you can always override with the config variable set to "yes"
if [ -z "$NEXT_BOOT" \
     -a "$SUSPEND2DISK_IGNORE_KERNEL_MISMATCH" != "yes" ]; then
    # which kernel is booted with the default entry?
    BOOTING="${KERNELS[$DEFAULT_BOOT]}"
    # if there is no default entry (no menu.lst? Using LILO?) we fall back to
    # the default of /boot/vmlinuz.
    [ -z "$BOOTING" ] && BOOTING="vmlinuz"
    if IMAGE=`readlink /boot/$BOOTING` && [ -e "/boot/${IMAGE##*/}" ]; then
        BOOTING=$IMAGE
    fi
    BOOTING="${BOOTING#*vmlinuz-}"
    DEBUG "running kernel: '$RUNNING', (probably) booting kernel: '$BOOTING'" DIAG
    echo  "running kernel: '$RUNNING', (probably) booting kernel: '$BOOTING'" >> $LSMOD_LOG
    if [ "$BOOTING" != "$RUNNING" ]; then
        notify 'The kernel version "'$BOOTING'" in /boot does not match the running kernel
version "'$RUNNING'". Resuming with this kernel will not work. If you know
what you are doing, you can override this in /etc/sysconfig/powersave/sleep
with the variable SUSPEND2DISK_IGNORE_KERNEL_MISMATCH=yes.' ERROR CONTINUE "$EV_ID"
        progress_finish
        echo "kernel version mismatch, cannot suspend to disk." >> $LSMOD_LOG
        $SCRIPT_RETURN $EV_ID 1 "kernel version mismatch, cannot suspend to disk."
        EXIT 1
    fi
fi

let PERCENT+=$STEP
progress "${_M02}"

################################################################
# this is a hack. We can swapon a dedicated partition before
# suspend. This partition will only be used by the suspend image
# after resume we swapoff it  again.
if [ -n "$SUSPEND2DISK_RESUME_DEVICE" ]; then
    DEBUG "activating suspend partition '$SUSPEND2DISK_RESUME_DEVICE'" DIAG
    echo "You have set SUSPEND2DISK_RESUME_DEVICE. This is for experts." >> $LSMOD_LOG
    echo "activating suspend partition '$SUSPEND2DISK_RESUME_DEVICE'" >> $LSMOD_LOG
    echo "swapon: $SUSPEND2DISK_RESUME_DEVICE" >> $STATE
    swapon "$SUSPEND2DISK_RESUME_DEVICE"
    RET=$?
    if [ $RET -ne 0 ]; then
        DEBUG "swapon $SUSPEND2DISK_RESUME_DEVICE failed. Error: $RET" WARN
        echo "could not activate $SUSPEND2DISK_RESUME_DEVICE. Suspend might fail." >> $LSMOD_LOG
    fi
fi

################################################################
# we need a swap partition, and it has to be given to the kernel
# with the resume= parameter
# Note: the suspend code can deal with multiple swap partitions,
#       but only the one given by resume= will be used.
# SUSPEND2DISK_SKIP_RESUME_CHECK is a "secret" parameter, since
# it should never be needed.
if [ "$SUSPEND2DISK_SKIP_RESUME_CHECK" != yes ]; then
    read RDEV < /sys/power/resume

    # no resume device set? Error.
    if [ "$RDEV" = "0:0" ]; then
        DEBUG "resume partition is not set up." ERROR
        echo "resume partition is not set up." >> $LSMOD_LOG
        notify "The resume partition is not set up. Probably you need to add
                a 'resume=...' option to your kernel command line and reboot.
                Suspend to disk and resume is not possible without a resume
                partition, please consult the documentation. You can skip this
                check by setting SUSPEND2DISK_SKIP_RESUME_CHECK to 'yes' in
                the sleep configuration file." ERROR CONTINUE "$EV_ID"
        progress_finish
        $SCRIPT_RETURN $EV_ID 1 "no resume parameter"
        EXIT 1
    fi
    #
    # is the resume= parameter correct?
    while read SDEV STYPE DUMMY; do
        [ "$STYPE" != "partition" ] && continue
        X=$(stat -c '$((0x%t)):$((0x%T))' $SDEV) # stat major:minor in HEX
        [ $? -ne 0 ] && continue
        SNUM=$(eval echo $X) # this converts "$((0x3)):$((0xf))" to "3:15"
        [ "$SNUM" = "$RDEV" ] && break
        SDEV=""              # not necessary, but for clarity :-)
    done < /proc/swaps
    if [ -z "$SDEV" ] ; then
        DEBUG "swap partition '$RDEV' not available" ERROR
        DEBUG "Contents of /proc/swaps:" DIAG
        while read LINE; do
            DEBUG "$LINE" DIAG
        done < /proc/swaps
        echo "swap partition '$RDEV' not available. Boom." >> $LSMOD_LOG
        echo "Content of /proc/swaps:" >> $LSMOD_LOG
        cat /proc/swaps >> $LSMOD_LOG
        notify "Swap partition '$RDEV' is not available, cannot suspend to disk." \
                ERROR CONTINUE "$EV_ID"
        progress_finish
        $SCRIPT_RETURN $EV_ID 1 "resume partition not available."
        EXIT 1
    fi
else
    echo "SUSPEND2DISK_SKIP_RESUME_CHECK=yes" >> $LSMOD_LOG
fi
# end of swap partition sanity check
################################################################

let PERCENT+=$STEP
progress ""
prepare_sleep "suspend2disk"

let PERCENT+=$STEP
progress ""

# set the bootloader to the running kernel
if [ -n "$NEXT_BOOT" ]; then
    progress "${_M09}"
    echo "preparing boot-loader: selecting entry $NEXT_BOOT, kernel /boot/$BOOTING" >> $LSMOD_LOG
    T1=`date +"%s%N"`
    sync; sync; sync # this is needed to speed up grub-once on reiserfs
    T2=`date +"%s%N"`
    let PERCENT+=$STEP
    progress "${_M10}"
    grub-once $NEXT_BOOT > /dev/null 2>&1
    T3=`date +"%s%N"`
    S=$(((T2-T1)/100000000)); S="$((S/10)).${S:0-1}"
    G=$(((T3-T2)/100000000)); G="$((G/10)).${G:0-1}"
    echo "  time needed for sync: $S seconds, time needed for grub: $G seconds." >> $LSMOD_LOG
else
    let PERCENT=+$STEP
fi

progress ""

# SET THE SHUTDOWN METHOD ######################################
# "platform" -> "real" S4, default.
# "shutdown" -> S5
# "firmware" -> S4bios, not really supported.
# "reboot" -> just reboot, only useful for debugging
# we do a sanity check after setting this since there are still
# kernels out there getting this wrong.
echo -n "${SUSPEND2DISK_SHUTDOWN_MODE:-platform}" > /sys/power/disk
RET=$?
if [ $RET -ne 0 ]; then
    DEBUG "could not set shutdown mode. errno: '$RET'" WARN
    DEBUG "a software-suspend enabled kernel is needed for suspend to disk" WARN
fi

# Set the image size ###########################################
# this is only valid for kernels from 2.6.16rc1 upwards
IMAGE=${SUSPEND2DISK_IMAGE_SIZE:-500}
SYSFS_IMGSZ="/sys/power/image_size"
if [ -r $SYSFS_IMGSZ -a -n "$SDEV" ]; then
    while read DEV TYPE SIZE USED PRI; do
        [ "$DEV" != "$SDEV" ] && continue # SDEV comes from above
        FREE=$[($SIZE-$USED)/1024]  # get free space on SDEV in MB
        if [ $FREE -lt $IMAGE ]; then
            IMAGE=$[$FREE-10]
        fi
        break   # we found the partition, no need to look further
    done < /proc/swaps
    DEBUG "calculated image_size: $IMAGE" DIAG
    echo "calculated image_size: $IMAGE" >> $LSMOD_LOG

    if [ $IMAGE -lt 0 ]; then
        IMAGE=0
    fi
    # SUSPEND2DISK_IMAGE_SIZE is in MB, but the kernel now expects bytes
    echo $[$IMAGE*1024*1024] > $SYSFS_IMGSZ
else
    DEBUG "no $SYSFS_IMGSZ found or suspend device ('$SDEV') empty." DIAG
fi

switch_to_vt

progress_finish
$SCRIPT_RETURN $EV_ID 0 "prepare_sleep finished successfully for $1"

EXIT 0