kexec-tools/kdump

278 lines
6.4 KiB
Bash

#! /bin/sh
#
# Copyright 2005 Red Hat, Inc.
# Author: Jeff Moyer <jmoyer@redhat.com>
# Modifications for SUSE from Chris Mason <mason@suse.com>
# Takashi Iwai <tiwai@suse.de>
#
# kdump
#
# Description: The kdump init script provides the support necessary for
# loading a kdump kernel into memory at system bootup time,
# and for copying away a vmcore at system panic time.
#
#
# /etc/init.d/kexec
### BEGIN INIT INFO
# Provides: kdump
# Required-Start: boot.localfs $remote_fs
# Should-Start:
# Required-Stop:
# Default-Start: 1 2 3 5
# Default-Stop:
# Short-Description: kdump core saving and boot configuration
# Description: kdump core saving and boot configuration
### END INIT INFO
. /etc/sysconfig/kdump
. /etc/rc.status
KEXEC=/sbin/kexec
KDUMP_HELPER=/usr/sbin/kdump-helper
KDUMP_CLEANUP_DUMPS=/usr/sbin/kdump-cleanup_dumps
KDUMP_SAVE_DUMP=/usr/sbin/kdump-save_dump
KDUMP_IDENTIFY_KERNEL=/usr/sbin/kdump-identify_kernel
BOOTDIR="/boot"
# The default dumper
#
# Clean up old stuff if necessary, check the free size
# and save the vmcore
save_core()
{
$KDUMP_CLEANUP_DUMPS
if [ "$?" -ne 0 ] ; then
rc_status -v
return 1
fi
$KDUMP_SAVE_DUMP /proc/vmcore
rc_status -v
return 0
}
# print the available kdump kernel path
# empty if no matching file is found
check_boot_kernel ()
{
local kstr
# if the kernel is relocatable, try vmlinuz first because
# currently there are bugs with relocatable ELF-Images
# (ET_DYN => GDB doesn't work / ET_EXEC => kexec-tools doesn't
# detect)
case `uname -i` in
x86_64|i386)
kstr="${BOOTDIR}/vmlinuz-$1$2"
if [ -f $kstr ] ; then
if $KDUMP_IDENTIFY_KERNEL -r $kstr &>/dev/null ; then
echo $kstr
return
fi
fi
esac
kstr="${BOOTDIR}/vmlinux-$1$2"
if [ -f $kstr ]; then
echo $kstr
return
fi
kstr="$kstr.gz"
if [ -f $kstr ]; then
echo $kstr
return
fi
case `uname -i` in
ia64)
# ia64 uses vmlinuz as of vmlinux.gz
kstr="${BOOTDIR}/vmlinuz-$1$2"
if [ -f $kstr ]; then
echo $kstr
return
fi
;;
esac
}
# Load the kdump kerel specified in /etc/sysconfig/kdump
# If none is specified, try to load a kdump kernel with the same version
# as the currently running kernel.
load_kdump()
{
echo -n "Loading kdump "
if [ -z "$KDUMP_KERNELVER" ]; then
kdump_kver=`uname -r | sed -e's/-[^-]*$//g'`
kdump_kernel=`check_boot_kernel $kdump_kver -kdump`
if [ -n "$kdump_kernel" ]; then
kdump_kver="${kdump_kver}-kdump"
elif [ -z "$kdump_kernel" ]; then
kdump_kver=`uname -r`
kdump_kernel=`check_boot_kernel $kdump_kver`
fi
else
kdump_kver="$KDUMP_KERNELVER"
kdump_kernel=`check_boot_kernel $kdump_kver`
fi
if [ -z "$kdump_kernel" -o ! -f "$kdump_kernel" ]; then
echo -n ": No kdump kernel image found for kernel $kdump_kver."
rc_status -s
rc_failed 6
rc_exit
fi
kdump_initrd="${BOOTDIR}/initrd-${kdump_kver}"
if [ ! -f $kdump_initrd ]; then
echo -n ": No kdump initial ramdisk found."
echo "Tried to locate ${kdump_initrd}"
rc_status -s
rc_failed 6
rc_exit
fi
if [ -z "$KDUMP_COMMANDLINE" ]; then
KDUMP_COMMANDLINE=`cat /proc/cmdline | \
sed -e 's/crashkernel=[0-9]\+[mM]\(@[0-9]\+[Mm]\?\)\?//g' \
-e 's/ *splash=[^ ]*/ /g' \
-e 's/ *BOOT_IMAGE=[^ ]* / /g' \
-e 's/ *showopts/ /g'`
# Use deadline for saving the memory footprint
KDUMP_COMMANDLINE="$KDUMP_COMMANDLINE elevator=deadline sysrq=1"
case `uname -i` in
i?86|x86_64|ia64)
KDUMP_COMMANDLINE="$KDUMP_COMMANDLINE irqpoll"
;;
esac
fi
KDUMP_COMMANDLINE="CRASH=1 $KDUMP_COMMANDLINE"
if [ -n "$KDUMP_COMMANDLINE_APPEND" ] ; then
KDUMP_COMMANDLINE="$KDUMP_COMMANDLINE $KDUMP_COMMANDLINE_APPEND"
fi
if [ -n "$KDUMP_RUNLEVEL" ]; then
case "$KDUMP_RUNLEVEL" in
[1-5s])
KDUMP_COMMANDLINE="$KDUMP_COMMANDLINE $KDUMP_RUNLEVEL"
;;
*)
echo " : Invalid KDUMP_RUNLEVEL=$KDUMP_RUNLEVEL, ignored"
;;
esac
fi
# add the dump device
if [ -n "$KDUMP_DUMPDEV" ] ; then
KDUMP_COMMANDLINE="dumpdev=$KDUMP_DUMPDEV $KDUMP_COMMANDLINE"
fi
echo 1 > /proc/sys/kernel/panic_on_oops
# remove `--args-linux' for x86 type kernel files here
if [ $($KDUMP_IDENTIFY_KERNEL -t $kdump_kernel) = "x86" ] ; then
KEXEC_OPTIONS=$(echo $KEXEC_OPTIONS | sed -e 's/--args-linux//g')
fi
KEXEC_CALL="$KEXEC -p $kdump_kernel --append=\"$KDUMP_COMMANDLINE\""
KEXEC_CALL="$KEXEC_CALL --initrd=$kdump_initrd $KEXEC_OPTIONS"
if [ $(($KDUMP_VERBOSE & 1)) -gt 0 ] ; then
logger -i -t kdump "Loading kdump kernel: $KEXEC_CALL"
fi
if [ $(($KDUMP_VERBOSE & 4)) -gt 0 ] ; then
echo "Loading kdump kernel: $KEXEC_CALL"
fi
eval "$KEXEC_CALL"
rc_status -v
}
# return success if running in a crash environemnt
is_crash_kernel ()
{
test -f /proc/vmcore || return 1
# FIXME: any better way to detect crash environment?
test -n "$CRASH" && return 0
grep -q elfcorehdr= /proc/cmdline && return 0
return 1
}
# return success if we have a valid dump on the dump device
have_valid_dump_in_dumpdev ()
{
if [ ! -b "$KDUMP_DUMPDEV" ] ; then
return 1
fi
# return the return code from this command
$KDUMP_HELPER -c "$KDUMP_DUMPDEV" >> /dev/null
}
# invalidate the dump device so that it's not read on next boot
invalidate_dumpdev ()
{
dd if=/dev/zero of=$KDUMP_DUMPDEV bs=512 count=1 &>/dev/null
}
case "$1" in
start)
if is_crash_kernel; then
if [ -z "$KDUMP_DUMPDEV" ] ; then
if [ -n "$KDUMP_TRANSFER" ]; then
$KDUMP_TRANSFER
else
save_core
fi
fi
if test "$KDUMP_IMMEDIATE_REBOOT" = "yes"; then
/sbin/reboot
# sleep to avoid the conflict with script "single"
sleep 600
fi
else
if have_valid_dump_in_dumpdev ; then
$KDUMP_SAVE_DUMP $KDUMP_DUMPDEV
rc_status -v
if [ "$?" -eq 0 ] ; then
invalidate_dumpdev
rc_status
fi
fi
load_kdump
fi
;;
stop)
if ! is_crash_kernel ; then
if [ "$RUNLEVEL" != "" ]; then
echo -n "Not unloading kdump during runlevel changes"
rc_status -s
else
echo -n "Unloading kdump"
$KEXEC -p -u
rc_status -v
fi
fi
;;
status)
echo "not implemented"
;;
restart|reload)
$0 stop
$0 start
;;
condrestart)
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload}"
exit 1
esac
exit $?
# vim: set ts=8 sw=4 sts=4 noet: