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
|