#!/bin/sh # # Licensed under the GPLv2 # # Copyright 2008, Red Hat, Inc. # Jeremy Katz emergency_shell() { exec >/dev/console 2>&1 /dev/null 2>&1 mount -t sysfs /sys /sys >/dev/null 2>&1 if [ ! -c /dev/ptmx ]; then # try to mount devtmpfs if ! mount -t devtmpfs -omode=0755 udev /dev >/dev/null 2>&1; then # if it failed fall back to normal tmpfs mount -t tmpfs -omode=0755 udev /dev >/dev/null 2>&1 # Make some basic devices first, let udev handle the rest mknod /dev/null c 1 3 mknod /dev/ptmx c 5 2 mknod /dev/console c 5 1 mknod /dev/kmsg c 1 11 fi fi if getarg rdinitdebug; then set -x fi mkdir /dev/shm mkdir /dev/pts mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts >/dev/null 2>&1 UDEVVERSION=$(udevadm --version) source_conf /etc/conf.d # run scriptlets to parse the command line getarg 'rdbreak=cmdline' && emergency_shell "Break before cmdline" source_all cmdline [ -z "$root" ] && die "No or empty root= argument" [ -z "$rootok" ] && die "Don't know how to handle 'root=$root'" # Network root scripts may need updated root= options, # so deposit them where they can see them (udev purges the env) { echo "root='$root'" echo "rflags='$rflags'" echo "fstype='$fstype'" echo "netroot='$netroot'" echo "NEWROOT='$NEWROOT'" } > /tmp/root.info # pre-udev scripts run before udev starts, and are run only once. getarg 'rdbreak=pre-udev' && emergency_shell "Break before pre-udev" source_all pre-udev # start up udev and trigger cold plugs udevd --daemon UDEV_LOG_PRIO_ARG=--log-priority UDEV_QUEUE_EMPTY="udevadm settle --timeout=0" if [ $UDEVVERSION -lt 140 ]; then UDEV_LOG_PRIO_ARG=--log_priority UDEV_QUEUE_EMPTY="udevadm settle --timeout=1" fi getarg rdudevinfo && udevadm control $UDEV_LOG_PRIO_ARG=info getarg rdudevdebug && udevadm control $UDEV_LOG_PRIO_ARG=debug getarg 'rdbreak=pre-trigger' && emergency_shell "Break before pre-trigger" source_all pre-trigger # then the rest udevadm trigger $udevtriggeropts >/dev/null 2>&1 getarg 'rdbreak=initqueue' && emergency_shell "Break before initqueue" i=0 while :; do # bail out, if we have mounted the root filesystem [ -d "$NEWROOT/proc" ] && break; # check if root can be mounted [ -e /dev/root ] && break; if [ $UDEVVERSION -ge 143 ]; then udevadm settle --exit-if-exists=/initqueue/work --exit-if-exists=/dev/root else udevadm settle --timeout=30 fi # bail out, if we have mounted the root filesystem [ -d "$NEWROOT/proc" ] && break; # check if root can be mounted [ -e /dev/root ] && break; unset queuetriggered if [ -f /initqueue/work ]; then rm /initqueue/work queuetriggered="1" fi for job in /initqueue/*.sh; do [ -e "$job" ] || break job=$job . $job # bail out, if we have mounted the root filesystem [ -d "$NEWROOT/proc" ] && break; # check if root can be mounted [ -e /dev/root ] && break; done [ -n "$queuetriggered" ] && continue if $UDEV_QUEUE_EMPTY >/dev/null 2>&1; then # no more udev jobs sleep 0.5 i=$(($i+1)) [ $i -gt 20 ] \ && { flock -s 9 ; emergency_shell "No root device found"; } 9>/.console_lock fi done unset job unset queuetriggered # pre-mount happens before we try to mount the root filesystem, # and happens once. getarg 'rdbreak=pre-mount' && emergency_shell "Break pre-mount" source_all pre-mount getarg 'rdbreak=mount' && emergency_shell "Break mount" # mount scripts actually try to mount the root filesystem, and may # be sourced any number of times. As soon as one suceeds, no more are sourced. i=0 while :; do [ -d "$NEWROOT/proc" ] && break; for f in /mount/*.sh; do [ -f "$f" ] && . "$f" [ -d "$NEWROOT/proc" ] && break; done i=$(($i+1)) [ $i -gt 20 ] \ && { flock -s 9 ; emergency_shell "Can't mount root filesystem"; } 9>/.console_lock done # We have the root file system mounted under $NEWROOT, so copy # the vmcore there and call it a day # DATEDIR=`date +%d.%m.%y-%T` mkdir -p $NEWROOT/var/crash/$DATEDIR cp /proc/vmcore /var/crash/$DATEDIR/vmcore # Once the copy is done, just reboot the system reboot -f