#!/bin/bash --norc # vim:sts=4:sw=4:ts=8:et # mkdumprd # # Copyright 2005 Red Hat, Inc. # # Written by Erik Troan # # Contributors: # Elliot Lee # Miguel de Icaza # Christian 'Dr. Disk' Hechelmann # Michael K. Johnson # Pierre Habraken # Jakub Jelinek # Carlo Arenas Belon (carenas@chasqui.lared.net.pe> # Keith Owens # Bernhard Rosenkraenzer # Matt Wilson # Trond Eivind Glomsrød # Jeremy Katz # Preston Brown # Bill Nottingham # Guillaume Cottenceau # Peter Jones # Neil Horman # Jarod Wilson cmdname=`basename $0` umask 0022 export MALLOC_PERTURB_=204 PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH export PATH . /etc/rc.d/init.d/functions VERSION=5.0.39 PROBE="yes" MODULES="" PREMODS="" DMRAIDS="" MPATHS="" CONFMODS="$MODULES" MODULES="" withusb=yes compress=1 allowmissing="" target="" kernel="" force="" verbose="" img_vers="" builtins="" modulefile=/etc/modules.conf rc=0 IMAGESIZE=8000 PRESCSIMODS="sd_mod" fstab="/etc/fstab" vg_list="" net_list="" USING_METHOD="" SAVE_PATH=/var/crash bin="" KDUMP_POST="" extra_kdump_mods="" TMPDISKLIST=`mktemp /tmp/disklist.XXXXXX` vecho() { NONL="" if [ "$1" == "-n" ]; then NONL="-n" shift fi [ -n "$verbose" ] && echo $NONL "$@" } error() { NONL="" if [ "$1" == "-n" ]; then NONL="-n" shift fi echo $NONL "$@" >&2 } usage () { if [ "$1" == "-n" ]; then cmd=echo else cmd=error fi $cmd "usage: $cmdname [--version] [--help] [-v] [-d] [-f] [--preload ]" $cmd " [--image-version]" $cmd " [--builtin=] [--omit-dmraid]" $cmd " [--fstab=] [--nocompress] " $cmd "" $cmd " (ex: $cmdname /boot/initrd-2.2.5-15.img 2.2.5-15)" if [ "$1" == "-n" ]; then exit 0 else exit 1 fi } moduledep() { if [ ! -f "/lib/modules/$kernel/modules.dep" ]; then error "No dep file found for kernel $kernel" exit 1 fi deps=$(awk 'BEGIN { searched=ARGV[2]; ARGV[2]=""; rc=1 } \ function modname(filename) { match(filename, /\/([^\/]+)\.k?o:?$/, ret); return ret[1] } \ function show() { if (orig == searched) { print dep; orig=""; rc=0; exit } } \ /^\/lib/ { show(); \ orig=modname($1); dep=""; \ if ($2) { for (i = 2; i <= NF; i++) { dep=sprintf("%s %s", dep, modname($i)); } } } \ /^ / { dep=sprintf("%s %s", dep, modname($1)); } \ END { show(); exit(rc) }' /lib/modules/$kernel/modules.dep $1) for i in `modprobe --show-depends $1 2>/dev/null | awk '/insmod/ {print $2}'` do modname=`basename $i | sed -e's/\.ko//'` if [ "$modname" == "$1" ] then continue fi deps="$deps $modname" done [ -n "$deps" ] && vecho ":$deps" || vecho } findone() { find "$@" -print -quit } dm_get_uuid() { dmsetup info "$1" | awk '/^.*UUID.*/ {print $2}' } depsolve_modlist() { local TMPINMODS=$MODULES local TMPOUTMODS="" local i local j local mname local dpcnt local scnt # # So, basically, we just do this until TMPINMODS # is an empty list # while [ -n "$TMPINMODS" ] do for i in $TMPINMODS do mname=`basename $i | sed -e's/\.ko//'` dpcnt=`modprobe --show-depends $mname 2>/dev/null | awk '/insmod/ {print $2}' | wc -l` if [ $dpcnt -le 1 ] then # we have no dependencies, just add it to the list echo "$TMPOUTMODS" | grep -q $i if [ $? -ne 0 ] then TMPOUTMODS="$TMPOUTMODS $i" fi continue fi # We should start this counter at 1, since we expect that the last # line output by modprobe --show-depends will be the module we # specify as mname below, but since modprobe is busted and # sometimes doesn't do that, we start at zero, and increment an # extra time below if we are searching for a dependency on ourself let scnt=0 for j in `modprobe --show-depends $mname 2>/dev/null | awk '/insmod/ {print $2}'` do echo $TMPOUTMODS | grep -q $j if [ $? -eq 0 ] then let scnt=$scnt+1 fi # here we are looking to see if the insmod line is for the # module that we are searching for dependencies on. We do this # because modprobe is busted in its show-depends line echo $j | grep -q $i if [ $? -eq 0 ] then let scnt=$scnt+1 fi done if [ "$scnt" == "$dpcnt" ] then echo "$TMPOUTMODS" | grep -q $i if [ $? -ne 0 ] then TMPOUTMODS="$TMPOUTMODS $i" fi fi #Finish for i loop done for j in $TMPOUTMODS do TMPTMPMODS="" for z in $TMPINMODS do if [ "$j" == "$z" ] then continue fi TMPTMPMODS="$TMPTMPMODS $z" done TMPINMODS=$TMPTMPMODS done done MODULES=$TMPOUTMODS } findmodule() { local skiperrors="" if [ $1 == "--skiperrors" ]; then skiperrors=--skiperrors shift fi local modName=$1 local skipdeps=$2 if [ "$modName" = "off" -o "$modName" = "null" ]; then return fi if [ $(echo $modName | cut -b1) = "-" ]; then skiperrors=--skiperrors modName=$(echo $modName | cut -b2-) fi case "$MODULES " in *"/$modName.ko "*) return ;; esac if echo $builtins | egrep -q '(^| )'$modName'( |$)' ; then vecho "module $modName assumed to be built in" return fi # special cases case "$modName" in raid[456]) modName=raid456 ;; esac if [ "$modName" = "i2o_block" ]; then findmodule i2o_core findmodule -i2o_pci modName="i2o_block" elif [ "$modName" = "ppa" ]; then findmodule parport findmodule parport_pc modName="ppa" elif [ "$modName" = "sbp2" ]; then findmodule ieee1394 findmodule ohci1394 modName="sbp2" elif [ "$modName" = "raid6" ]; then findmodule raid456 modName="raid456" else if [ -z "$skipdeps" ] then moduledep $modName for i in $deps; do findmodule $i done fi fi fmPath=$(modprobe --set-version $kernel -l $modName 2>/dev/null) if [ ! -f "/lib/modules/$kernel/$fmPath" ]; then for modDir in /lib/modules/$kernel/updates /lib/modules/$kernel do if [ -d $modDir ] then fmPath=$(findone $modDir -name $modName.ko) if [ -f "$fmPath" ] then break 2 fi fi done fi if [ ! -f "/lib/modules/$kernel/$fmPath" ]; then if [ -n "$skiperrors" ]; then return fi # ignore the absence of the scsi modules for n in $PRESCSIMODS; do if [ "$n" = "$modName" ]; then return; fi done; if [ -n "$allowmissing" ]; then error "WARNING: No module $modName found for kernel $kernel, continuing anyway" return fi error "No module $modName found for kernel $kernel, aborting." exit 1 fi # only need to add each module once MODULES="$MODULES /lib/modules/$kernel/$fmPath" # need to handle prescsimods here -- they need to go _after_ scsi_mod if [ "$modName" = "scsi_mod" ]; then for n in $PRESCSIMODS ; do findmodule $n done fi } do_blacklist() { local modName=$1 if echo "$modName" | grep -q "\/" ; then local dirName="/lib/modules/$kernel/$modName" find $dirName -xtype f -exec basename {} \; | sed "s/^\(.*\).ko/blacklist \1/g" >> $MNTIMAGE/etc/blacklist-kdump.conf else echo "blacklist $modName" >> $MNTIMAGE/etc/blacklist-kdump.conf fi } inst() { if [ "$#" != "2" ];then echo "usage: inst " return fi vecho "$1 -> $2" cp $1 $2 } findstoragedriverinsys () { while [ ! -L device ]; do [ "$PWD" = "/sys" ] && return cd .. done cd $(readlink ./device) while [ ! -f modalias ]; do [ "$PWD" = "/sys/devices" ] && return cd .. done modalias=$(cat modalias) for driver in $(modprobe --set-version $kernel --show-depends $modalias 2>/dev/null| awk '{ print gensub(".*/","","g",$2) }') ; do findmodule ${driver%%.ko} done # Handle special needs for missing deps or wierd modalias lines case $modalias in "scsi:t-0x00") findmodule ata_generic ;; *) ;; esac } findstoragedriver () { for device in $@ ; do basedev=`echo $device | sed -e's/\/dev\///' -e's/[0-9]\+//'` if [ -d /sys/block/$basedev ] then #only add devices which have a presence in sysfs echo $basedev >> $TMPDISKLIST fi case " $handleddevices " in *" $device "*) continue ;; *) handleddevices="$handleddevices $device" ;; esac echo $device | grep -q "md[0-9]\+" if [ $? == 0 ]; then vecho "Found RAID component $device" handleraid "$device" continue fi device=`echo $device | sed 's/\//\!/g'` sysfs=$(findone -L /sys/block -maxdepth 2 -type d -name $device) [ -z "$sysfs" ] && return pushd $sysfs >/dev/null 2>&1 findstoragedriverinsys popd >/dev/null 2>&1 done } findnetdriver() { for device in $@ ; do case " $handleddevices " in *" $device "*) continue ;; *) handleddevices="$handleddevices $device" ;; esac case "$device" in bond*) modalias=bonding ;; eth*.*) modalias=8021q ;; *) if [ -f /sys/class/net/$device/device/modalias ] then modalias=$(cat /sys/class/net/$device/device/modalias) else modalias=$(ethtool -i $device | awk '/^driver:/ { print $2 }') fi ;; esac for driver in $(modprobe --set-version $kernel --show-depends $modalias 2>/dev/null| awk '{ print gensub(".*/","","g",$2) }') ; do findmodule ${driver%%.ko} done done } handleraid() { echo IN HANDLERAID local start=0 if [ -n "$noraid" -o ! -f /proc/mdstat ]; then return 0 fi levels=$(grep "^$1[ ]*:" /proc/mdstat | \ awk '{ print $4 }') devs=$(grep "^$1[ ]*:" /proc/mdstat | \ awk '{ print gensub("\\[[0-9]*\\]","","g",gensub("^md.*raid[0-9]*","","1")) }') for level in $levels ; do case $level in linear) findmodule linear start=1 ;; multipath) findmodule multipath start=1 ;; raid[01456] | raid10) findmodule $level start=1 ;; *) error "raid level $level (in /proc/mdstat) not recognized" ;; esac done findstoragedriver $devs if [ "$start" = 1 ]; then raiddevices="$raiddevices $1" fi return $start } handlelvordev() { local vg=`lvs --noheadings -o vg_name $1 2>/dev/null` if [ -z "$vg" ]; then vg=`lvs --noheadings -o vg_name $(echo $1 | sed -e 's#^/dev/mapper/\([^-]*\)-\(.*\)$#/dev/\1/\2#') 2>/dev/null` fi if [ -n "$vg" ]; then vg=`echo $vg` # strip whitespace case " $vg_list " in *" $vg "*) ;; *) vg_list="$vg_list $vg" for device in `vgdisplay -v $vg 2>/dev/null | sed -n 's/PV Name//p'`; do IS_UUID=`echo $device | grep UUID` IS_LABEL=`echo $device | grep LABEL` if [ -n "$IS_UUID" -o -n "$IS_LABEL" ] then devname=`findfs $device` else devname=$device fi findstoragedriver ${device##/dev/} done ;; esac else IS_UUID=`echo $1 | grep UUID` IS_LABEL=`echo $1 | grep LABEL` if [ -n "$IS_UUID" -o -n "$IS_LABEL" ] then devname=`findfs $1` else devname=$1 fi findstoragedriver ${1##/dev/} fi } handlenetdev() { local dev=$1 cp /etc/sysconfig/network-scripts/ifcfg-$dev $MNTIMAGE/etc BOOTPROTO="" VLAN="" MASTER="" SLAVE="" . $MNTIMAGE/etc/ifcfg-$dev findnetdriver $dev if [ "$BOOTPROTO" == "dhcp" ] then echo iface $dev inet dhcp >> $MNTIMAGE/etc/network/interfaces else echo iface $dev inet static >> $MNTIMAGE/etc/network/interfaces if [ -n "$IPADDR" ] then echo " " address $IPADDR >> $MNTIMAGE/etc/network/interfaces fi if [ -n "$NETMASK" ] then echo " " netmask $NETMASK >> $MNTIMAGE/etc/network/interfaces fi if [ -z "$GATEWAY" ] then GATEWAY=`/sbin/ip route show | awk '/^default/ {print $3}'` fi echo " " gateway $GATEWAY >> $MNTIMAGE/etc/network/interfaces fi #This lets us recursively handle stacked devices case "$dev" in bond*) #This is a bond, pick up its slaves for j in `cat /sys/class/net/$dev/bonding/slaves` do handlenetdev $j done echo "BUS_ID=\"Bonding\"" >> $MNTIMAGE/etc/ifcfg-$dev ;; *) if [ "$VLAN" == "yes" ] then #put code to handle vlan devices echo "BUS_ID=\"Vlan\"" >> $MNTIMAGE/etc/ifcfg-$dev #now make sure we pick up the driver to support the #underlying interface BASE_IFC=`echo $dev | cut -d"." -f1` handlenetdev $BASE_IFC else BUS_ID=`ls -l /sys/class/net/$dev/device | sed -e's/\(.*\/\)\(.*$\)/\2/'` echo "BUS_ID=\"$BUS_ID\"" >> $MNTIMAGE/etc/ifcfg-$dev fi ;; esac } while [ $# -gt 0 ]; do case $1 in --fstab*) if echo $1 | grep -q '=' ; then fstab=`echo $1 | sed 's/^--fstab=//'` else fstab=$2 shift fi ;; --with-usb) withusb=yes ;; --without-usb) withusb=no ;; --with*) if echo $1 | grep -q '=' ; then modname=`echo $1 | sed 's/^--with=//'` else modname=$2 shift fi basicmodules="$basicmodules $modname" ;; --builtin*) if echo $1 | grep -q '=' ; then modname=`echo $1 | sed 's/^--builtin=//'` else modname=$2 shift fi builtins="$builtins $modname" ;; --version) echo "$cmdname: version $VERSION" exit 0 ;; -v) verbose=-v ;; --nocompress) compress="" ;; --ifneeded) # legacy ;; -f) force=1 ;; -d) KDUMP_CONFIG_FILE="" if [ -f /etc/kdump.conf ]; then KDUMP_CONFIG_FILE="/etc/kdump.conf" fi ;; --preload*) if echo $1 | grep -q '=' ; then modname=`echo $1 | sed 's/^--preload=//'` else modname=$2 shift fi PREMODS="$PREMODS $modname" ;; --force-scsi-probe) forcescsi=1 ;; --omit-scsi-modules) PRESCSIMODS="" noscsi=1 ;; --force-raid-probe) forceraid=1 ;; --omit-raid-modules) noraid=1 ;; --force-lvm-probe) forcelvm=1 ;; --omit-lvm-modules) nolvm=1 ;; --omit-dmraid) nodmraid=1 ;; --force-ide-probe) forceide=1 ;; --image-version) img_vers=yes ;; --allow-missing) allowmissing=yes ;; --noresume) noresume=1 ;; --help) usage -n ;; *) if [ -z "$target" ]; then target=$1 elif [ -z "$kernel" ]; then kernel=$1 else usage fi ;; esac shift done if [ -z "$target" -o -z "$kernel" ]; then usage fi if [ -n "$img_vers" ]; then target="$target-$kernel" fi if [ -z "$force" -a -f $target ]; then error "$target already exists." exit 1 fi if [ -n "$forcescsi" -a -n "$noscsi" ]; then error "Can't both force scsi probe and omit scsi modules" exit 1 fi if [ -n "$forceraid" -a -n "$noraid" ]; then error "Can't both force raid probe and omit raid modules" exit 1 fi if [ -n "$forcelvm" -a -n "$nolvm" ]; then error "Can't both force LVM probe and omit LVM modules" exit 1 fi if [ ! -d /lib/modules/$kernel ]; then error 'No modules available for kernel "'${kernel}'".' exit 1 fi if [ $UID != 0 ]; then error "$cmdname must be run as root." exit 1 fi vecho "Creating initramfs" modulefile=/etc/modprobe.conf # find a temporary directory which doesn't use tmpfs TMPDIR="" for t in /tmp /var/tmp /root ${PWD}; do if [ ! -d $t ]; then continue; fi fs=$(df -T $t 2>/dev/null | awk '{line=$1;} END {printf $2;}') if [ "$fs" != "tmpfs" ]; then TMPDIR=$t break fi done if [ -z "$TMPDIR" ]; then error "no temporary directory could be found." exit 1 fi if [ $TMPDIR = "/root" -o $TMPDIR = "${PWD}" ]; then error "WARNING: using $TMPDIR for temporary files" fi for n in $PREMODS; do findmodule $n done needusb="" if [ -n "$withusb" -a "x$PROBE" == "xyes" ]; then # If / or /boot is on a USB device include the driver. With root by # label we could still get some odd behaviors for fs in / /boot ; do esc=$(echo $fs | sed 's,/,\\/,g') dev=$(mount | awk "/ on ${esc} / { print \$1 }" | sed 's/[0-9]*$//' | cut -d/ -f3) if [ "$(echo $dev | cut -c1-2)" = sd ]; then if [ `which kudzu 2>/dev/null` ]; then host=$(kudzu --probe -b scsi | gawk '/^device: '${dev}'/,/^host:/ { if (/^host/) { print $2; exit; } }') if [ -d /proc/scsi/usb-storage-${host} -o -f /proc/scsi/usb-storage/${host} ]; then needusb=1 fi fi fi done fi if [ -n "$needusb" -a "x$PROBE" == "xyes" ]; then drivers=$(awk '/^alias[[:space:]]+usb-controller[0-9]* / { print $3}' < $modulefile) useUSB=0 if [ -n "$drivers" ]; then useUSB=1 for driver in $drivers; do findmodule $driver done fi for x in $(grep ^[eou]hci_hcd /proc/modules | awk '{ print $1 }' | tac) ; do useUSB=1 findmodule $(echo $x | sed 's/_/-/') done if [ "$useUSB" == "1" ]; then findmodule scsi_mod findmodule sd_mod findmodule usb-storage fi fi if [ -n "$forcescsi" -o -z "$noscsi" -a "x$PROBE" == "xyes" ]; then if [ ! -f $modulefile ]; then modulefile=/etc/conf.modules fi if [ -f $modulefile ]; then scsimodules=`grep "alias[[:space:]]\+scsi_hostadapter" $modulefile | grep -v '^[ ]*#' | LC_ALL=C sort -u | awk '{ print $3 }'` if [ -n "$scsimodules" ]; then for n in $scsimodules; do # for now allow scsi modules to come from anywhere. There are some # RAID controllers with drivers in block/ findmodule $n done fi fi fi # If we have ide devices and module ide, do the right thing ide=/proc/ide/ide* if [ -n "$forceide" -o -n "$ide" -a "x$PROBE" == "xyes" ]; then findmodule -ide-disk fi # If we have dasd devices, include the necessary modules (S/390) if [ "x$PROBE" == "xyes" -a -d /proc/dasd ]; then findmodule -dasd_mod findmodule -dasd_eckd_mod findmodule -dasd_fba_mod fi if [ "x$PROBE" == "xyes" ]; then rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' $fstab) rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' $fstab) # in case the root filesystem is modular findmodule -${rootfs} rootdev=$(awk '/^[ \t]*[^#]/ { if ($2 == "/") { print $1; }}' $fstab) # check if it's nfsroot if [ "$rootfs" == "nfs" ]; then remote=$(echo $rootdev | cut -d : -f 1) # FIXME: this doesn't handle ips properly remoteip=$(getent hosts $remote | cut -d ' ' -f 1) netdev=`/sbin/ip route get to $remoteip |sed 's|.*dev \(.*\).*|\1|g' |awk {'print $1;'} |head -n 1` net_list="$net_list $netdev" # check if it's root by label elif echo $rootdev | cut -c1-6 | grep -q "UUID=\|LABEL=" ; then dev=`/sbin/findfs $rootdev | sed -e's/\(.*\/\)\(.*$\)/\2/' -e's/[0-9]\+//'` if [ -n "$dev" ] ; then vecho "Found root device $dev for $rootdev" rootdev=$dev fi else rootopts=$(echo $rootopts | sed -e 's/^r[ow],//' -e 's/,r[ow],$//' -e 's/,r[ow],/,/' \ -e 's/^r[ow]$/defaults/' -e 's/$/,ro/') fi [ "$rootfs" != "nfs" ] && handlelvordev $rootdev fi # If we use LVM or dm-based raid, include dm-mod # XXX: dm not really supported yet. testdm="" [ -n "$vg_list" ] && testdm="yes" [ -n "$forceraid" -o -n "$forcelvm" ] && testdm="yes" [ -z "$nolvm" -o -z "$noraid" ] && testdm="yes" [ "x$PROBE" != "xyes" ] && testdm="" if [ -n "$testdm" ]; then if [ -x /sbin/dmsetup -a -e /dev/mapper/control ]; then dmout=$(/sbin/dmsetup ls 2>/dev/null) if [ "$dmout" != "No devices found" -a "$dmout" != "" ]; then findmodule -dm-mod # DM requires all of these to be there in case someone used the # feature. broken. (#132001) findmodule -dm-mirror findmodule -dm-zero findmodule -dm-snapshot fi fi if [ -x /sbin/dmraid -a -z "$nodmraid" ]; then NOBLK=`/sbin/dmraid -s -craidname 2>/dev/null | grep "no block devices"` NORAD=`/sbin/dmraid -s -craidname 2>/dev/null | grep "no raid disks"` if [ -z "$NOBLK" ] && [ -z "$NORAD" ] then for raid in $(/sbin/dmraid -s -craidname 2>/dev/null) ; do DMRAIDS="$DMRAIDS $raid" done fi fi fi for n in $basicmodules; do findmodule $n done for n in $CONFMODS; do findmodule $n done vecho "Using modules:$MODULES" MNTIMAGE=`mktemp -d ${TMPDIR}/initrd.XXXXXX` IMAGE=`mktemp ${TMPDIR}/initrd.img.XXXXXX` RCFILE=$MNTIMAGE/init cemit() { cat >> $RCFILE } emit() { NONL="" if [ "$1" == "-n" ]; then NONL="-n" shift fi echo $NONL "$@" >> $RCFILE } emitdm() { vecho "Adding dm map \"$1\"" UUID=$(dm_get_uuid "$1") if [ -n "$UUID" ]; then UUID="--uuid $UUID" fi emit "echo \"$(/sbin/dmsetup table $1)\" | /sbin/dmsetup create \"$1\" $UUID" } emitdms() { [ -z "$MPATHS" -a -z "$DMRAIDS" ] && return 0 echo dm list $MPATHS $DMRAIDS | nash --force --quiet | \ while read ACTION NAME ; do case $ACTION in rmparts) emit rmparts "$NAME" ;; create) emitdm "$NAME" ;; part) emit /sbin/kpartx -pp -a \"/dev/mapper/$NAME\" ;; esac done } if [ -z "$MNTIMAGE" -o -z "$IMAGE" ]; then error "Error creating temporaries. Try again" exit 1 fi # Just get all the modules that are currently loaded # We're likely to need them for i in `lsmod | tail --lines=+2 | awk '{print $1}'` do findmodule -$i skip echo $MODULES | grep -q $i if [ $? -ne 0 ] then ALTERNATE=`echo $i | sed -e's/_/-/g'` findmodule $ALTERNATE skip fi done #START BUILDING INITRD HERE mkdir -p $MNTIMAGE mkdir -p $MNTIMAGE/lib mkdir -p $MNTIMAGE/bin mkdir -p $MNTIMAGE/etc mkdir -p $MNTIMAGE/dev mkdir -p $MNTIMAGE/proc mkdir -p $MNTIMAGE/sys mkdir -p $MNTIMAGE/tmp mkdir -p $MNTIMAGE/sysroot mkdir -p $MNTIMAGE/modules mkdir -p $MNTIMAGE/usr/share/udhcpc mkdir -p $MNTIMAGE/var/run mkdir -p $MNTIMAGE/etc/network/if-pre-up.d mkdir -p $MNTIMAGE/etc/network/if-up.d mkdir -p $MNTIMAGE/etc/network/if-pre-down.d mkdir -p $MNTIMAGE/etc/network/if-down.d mkdir -p $MNTIMAGE/etc/network/if-post-down.d ln -s bin $MNTIMAGE/sbin if [ -n "$KDUMP_CONFIG_FILE" ]; then while read config_opt config_val; do case "$config_opt" in net) #grab remote host and xlate into numbers rhost=`echo $config_val | sed 's/.*@//' | cut -d':' -f1` USE_SSH=`echo $config_val | grep @` if [ -n "$USE_SSH" ]; then USING_METHOD="ssh" else USING_METHOD="nfs" fi need_dns=`echo $rhost|grep [a-zA-Z]` [ -n "$need_dns" ] && rhost=`getent hosts $rhost|cut -d' ' -f1` #find ethernet device used to route to remote host, ie eth0 netdev=`/sbin/ip route get to $rhost 2>&1` [ $? != 0 ] && echo "Bad kdump location: $config_val" && exit 1 #the field in the ip output changes if we go to another subnet OFF_SUBNET=`echo $netdev | grep via` if [ -n "$OFF_SUBNET" ] then # we are going to a different subnet netdev=`echo $netdev|awk '{print $5;}'|head -n 1` else # we are on the same subnet netdev=`echo $netdev|awk '{print $3}'|head -n 1` fi #add the ethernet device to the list of modules mkdir -p $MNTIMAGE/etc/network/ handlenetdev $netdev echo $netdev >> $MNTIMAGE/etc/iface_to_activate #load nfs modules, if needed echo $config_val | grep -v "@" > /dev/null && findmodule nfs ;; raw) USING_METHOD="raw" if (echo $config_val | egrep -q "^(LABEL|UUID)="); then config_val=$(findfs $config_val) fi handlelvordev $config_val ;; core_collector) if [ -x /sbin/makedumpfile ]; then CORE_COLLECTOR=$config_val grep -q control_d /proc/xen/capabilities 2>/dev/null if [ $? -eq 0 ] then if [ -e /sys/kernel/vmcoreinfo ] then CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/makedumpfile/makedumpfile --message-level 1/'` else CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/makedumpfile/makedumpfile --xen-vmcoreinfo \/etc\/makedumpfile.config --message-level 1/'` fi else if [ -e /sys/kernel/vmcoreinfo ] then CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/makedumpfile/makedumpfile --message-level 1/'` else CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/makedumpfile/makedumpfile -i \/etc\/makedumpfile.config --message-level 1/'` fi fi else echo "Cannot use the core_collector option on this arch" rm -rf $MNTIMAGE rm -rf $IMAGE rm -f $TMPDISKLIST exit 1 fi ;; path) SAVE_PATH=$config_val ;; link_delay) LINK_DELAY=$config_val ;; kdump_post) KDUMP_POST=$config_val if [ ! -x "$KDUMP_POST" ]; then echo "$KDUMP_POST not executable or not found" exit 1 fi bin="$bin $KDUMP_POST" KDUMP_POST_INTERNAL=`echo $KDUMP_POST | sed -e's/\(^.*\/\)\(.*$\)/\/bin\/\2/'` ;; kdump_pre) KDUMP_PRE=$config_val if [ ! -x "$KDUMP_PRE" ]; then echo "$KDUMP_PRE not executable or not found" exit 1 fi bin="$bin $KDUMP_PRE" KDUMP_PRE_INTERNAL=`echo $KDUMP_PRE | sed -e's/\(^.*\/\)\(.*$\)/\/bin\/\2/'` ;; extra_bins) bin="$bin $config_val" ;; extra_modules) extra_kdump_mods="$extra_kdump_mods $config_val" ;; blacklist) blacklist_mods="$blacklist_mods $config_val" ;; options) ;; default) DEFAULT_ACTION=$config_val case $DEFAULT_ACTION in reboot|shell) FINAL_ACTION="reboot -f" ;; halt) FINAL_ACTION="halt -f" ;; poweroff) FINAL_ACTION="poweroff -f" ;; esac ;; disk_timeout) DISK_TIMEOUT=$config_val ;; *) IS_COMMENT=`echo $config_opt | grep "^#.*$"` if [ -n "$IS_COMMENT" -o -z "$config_opt" ] then #don't process comments or blank line continue fi let grep_rc=0 echo $config_opt | grep -q "ext[234]" ga_rc=$? echo $config_opt | grep -q "minix" gb_rc=$? echo $config_opt | grep -q "xfs" gc_rc=$? echo $config_opt | grep -q "btrfs" gd_rc=$? if [ $ga_rc -ne 0 -a $gb_rc -ne 0 -a $gc_rc -ne 0 -a $gd_rc -ne 0 ] then echo "Unknown parameter " $config_opt exit 1 fi USING_METHOD="filesystem" if (echo $config_val | egrep -q "^(LABEL|UUID)="); then config_val=$(findfs $config_val) fi handlelvordev $config_val ;; esac done < $KDUMP_CONFIG_FILE fi #if we are using makedumpfile here, then generate the config file #also only build this config if we don't have vmcoreinfo on this kernel if [ -n "$CORE_COLLECTOR" -a ! -e /sys/kernel/vmcoreinfo ]; then if [ -z "$USING_METHOD" ] then echo "Warning! Lack of dump target specification means core_collector option is ignored!" CORE_COLLECTOR="" else RUN_KERN_VER=`uname -r` if [ ! -f /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux ] then echo "kernel-debuginfo-$RUN_KERN_VER is not installed. You need this to use makedumpfile!" echo "please install it and restart the kdump service" rm -rf $MNTIMAGE rm -rf $IMAGE rm -f $TMPDISKLIST exit 1 fi XEN_OPTS="" grep -q control_d /proc/xen/capabilities 2>/dev/null if [ $? -eq 0 ] then # This is a dom0 xen kernel so we need to add xen-syms to the # makedumpefile config RUN_XEN_VER=${RUN_KERN_VER%xen} if [ ! -f /usr/lib/debug/boot/xen-syms-$RUN_XEN_VER.debug ] then echo "xen-syms.debug not found and is needed on this kernel to use makedumpfile!" echo "please install it and restart the kdump service" rm -rf $MNTIMAGE rm -rf $IMAGE rm -f $TMPDISKLIST exit 1 fi XEN_OPTS="--xen-syms /usr/lib/debug/boot/xen-syms-$RUN_XEN_VER.debug" /sbin/makedumpfile -g $MNTIMAGE/etc/makedumpfile.config $XEN_OPTS > /dev/null 2>&1 else /sbin/makedumpfile -g $MNTIMAGE/etc/makedumpfile.config -x /usr/lib/debug/lib/modules/$RUN_KERN_VER/vmlinux > /dev/null 2>&1 fi if [ $? != 0 ]; then echo "could not generate makedumpfile configuration. aborting" rm -rf $MNTIMAGE rm -rf $IMAGE rm -f $TMPDISKLIST exit 1; fi fi fi #include extra user-specified modules for kdump initrd for n in $extra_kdump_mods; do findmodule $n done # After we get all the modules, lets depsolve the list # so that we load them in proper order depsolve_modlist for n in $blacklist_mods; do do_blacklist $n done if [ -z "$FINAL_ACTION" ]; then FINAL_ACTION="reboot -f" else if [ -z "$USING_METHOD" ]; then echo "Warning! Lack of dump target specification means default option is ignored!" DEFAULT_ACTION="" FINAL_ACTION="reboot -f" fi fi #copy in busybox and make symlinks to its supported utilities cp /sbin/busybox $MNTIMAGE/sbin/busybox bin="$bin /sbin/busybox" cd $MNTIMAGE/sbin for i in `/sbin/busybox | awk 'BEGIN {found=0} /.*/ { if (found) print $0 } /Currently/ {found=1}' | sed -e's/,//g' -e's/busybox//g'` do ln -s busybox $MNTIMAGE/sbin/$i done cd - > /dev/null 2>&1 if [ -f /etc/mdadm.conf ] then cp /etc/mdadm.conf $MNTIMAGE/etc bin="$bin /sbin/mdadm" for i in `cat /etc/mdadm.conf | grep ARRAY | sed -e's/\(^.*level=\)\(.*$\)/\2/' | cut -d" " -f1` do findmodule $i done fi # we need the fstab file so that we can fsck properly cp /etc/fstab $MNTIMAGE/etc/fstab bin="$bin /sbin/fsck.ext2 /sbin/fsck.ext3 /sbin/fsck.ext4" #this provides us with a list of disks that we need to make sure we have available before we capture our core # don't block on cciss or md devices, parsing them in sysfs takes a special case and they are there # as soon as the driver loads egrep -v '(^cciss|^md)' $TMPDISKLIST > $MNTIMAGE/etc/critical_disks rm -f $TMPDISKLIST #THIS IS WHERE WE GENERATE OUR ADDITINONAL UTILITIES #Busybox doesn't have a /bin/sh applet, #so we build a reasonable faximilie here cat >> $MNTIMAGE/bin/sh << EOF #!/bin/msh #drop the -c from the command line shift 1 #now execute the passed command #don't exec this or $@ won't work /bin/msh -c "\$@" EOF chmod 755 $MNTIMAGE/bin/sh cat >> $MNTIMAGE/usr/share/udhcpc/default.script << EOF #!/bin/msh [ -z "\$1" ] && echo "Error: should be called from udhcpc" && exit 1 case "\$1" in deconfig) /sbin/ifconfig \$interface 0.0.0.0 ;; renew|bound) /sbin/ifconfig \$interface \$ip netmask \$subnet if [ -n "\$router" ] ; then echo "deleting routers" while route del default gw 0.0.0.0 dev \$interface ; do : done for i in \$router ; do route add default gw \$i dev \$interface done fi echo -n > /etc/resolv.conf [ -n "\$domain" ] && echo search $domain >> /etc/resolv.conf for i in \$dns ; do echo adding dns \$i echo nameserver \$i >> /etc/resolv.conf done ;; esac exit 0 EOF #NETWORKING SCRIPT DIRECTORIES cat >> $MNTIMAGE/etc/network/if-pre-up.d/pre-up-script << EOF #!/bin/msh PATH=\$PATH:/scriptfns . /etc/ifcfg-\$IFACE LINK_DELAY=$LINK_DELAY if [ "\$BUS_ID" != "Vlan" ] then ifconfig \$IFACE up if [ -n "\$LINK_DELAY" ] then echo "\$IFACE Link Up. Waiting \$LINK_DELAY Seconds" sleep \$LINK_DELAY echo "Continuing" fi fi if [ "\$BUS_ID" == "Bonding" ] then #this is a bond find and bring up the slaves echo searching for slaves find_activate_slaves \$IFACE elif [ "\$BUS_ID" == "Vlan" ] then #bring up the base interface first BASE_DEV=\`echo \$IFACE | cut -d"." -f1\` VLAN_ID=\`echo \$IFACE | cut -d"." -f2\` ifconfig \$BASE_DEV up if [ -n "\$LINK_DELAY" ] then echo "\$IFACE Link Up. Waiting \$LINK_DELAY Seconds" sleep \$LINK_DELAY echo "Continuing" fi vconfig add \$BASE_DEV \$VLAN_ID ifconfig \$IFACE up fi exit 0 EOF for i in `ls $MNTIMAGE/etc/network/if-pre-up.d` do chmod 755 $MNTIMAGE/etc/network/if-pre-up.d/$i done cat >> $MNTIMAGE/etc/network/if-up.d/up-script << EOF #!/bin/msh PATH=\$PATH:/scriptfns if [ "\$METHOD" != "dhcp" ] then . /etc/ifcfg-\$IFACE ifconfig \$IFACE \$IPADDR netmask \$NETMASK route add default gw \$GATEWAY dev \$IFACE fi exit 0 EOF for i in `ls $MNTIMAGE/etc/network/if-up.d` do chmod 755 $MNTIMAGE/etc/network/if-up.d/$i done chmod 755 $MNTIMAGE/usr/share/udhcpc/default.script # WE DONT HAVE FUNCTIONS AVAILABLE IN MSH # SO WE IMPLEMENT THEM HERE AS scripts SCRIPTDIR=$MNTIMAGE/scriptfns mkdir -p $SCRIPTDIR cat >> $SCRIPTDIR/map_interface << EOF #!/bin/msh if [ -e /tmp/tmpcnt ] then TMPCNT=\`cat /tmp/tmpcnt\` else TMPCNT=0 fi #erase previously recorded map RENAMED="" REAL_DEV="" NETDEV=\$1 . /etc/ifcfg-\$NETDEV for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\` do case "\$BUS_ID" in Bonding) REAL_DEV=bond0 RENAMED="yes" ;; Vlan) BASE_DEV=\`echo \$NETDEV | cut -d"." -f1\` VLAN_ID=\`echo \$NETDEV | cut -d"." -f2\` REAL_BASE=\`grep "^\$BASE_DEV " /etc/iface_map | cut -d" " -f2\` #Note we add the \ to our vlan values to escape the . for sed-ability #Note we also convert . to _ to avoid problems with busybox ifup REAL_DEV=\$REAL_BASE\\\\.\$VLAN_ID NETDEV=\$BASE_DEV\\\\.\$VLAN_ID RENAMED="yes" ;; *) INFO=\`ls -l /sys/class/net/\$j/device 2>/dev/null | sed -e's/\\(.*\\/\\)\\(.*$\\)/\\2/'\` if [ "\$INFO" == "\$BUS_ID" -a -z "\$REAL_DEV" ] then REAL_DEV=\$j RENAMED="yes" fi ;; esac done if [ -z "\$RENAMED" ] then echo "Could not find a mapping for device \$NETDEV" exit 1 fi #build the interface rename map echo \$NETDEV \$REAL_DEV tmp\$TMPCNT >> /etc/iface_map TMPCNT=\`echo \$TMPCNT 1 + p | dc\` echo \$TMPCNT > /tmp/tmpcnt echo mapping \$NETDEV to \$REAL_DEV EOF cat >> $SCRIPTDIR/rename_interfaces << EOF #!/bin/msh MAP_COUNT=\`wc -l /etc/iface_map | cut -d" " -f7 \` #now do all the renaming - first to temp space for j in \`seq 1 1 \$MAP_COUNT\` do CURRENT=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$1}' /etc/iface_map\` NEW=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$2}' /etc/iface_map\` INTERIM=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$3}' /etc/iface_map\` mv /etc/ifcfg-\$CURRENT /etc/ifcfg-\$INTERIM for i in /etc/ifcfg-\$INTERIM /etc/iface_to_activate /etc/network/interfaces do # the double quotes lets us expand the variables sed -e"s/\$CURRENT/\$INTERIM/g" \$i > \$i.tmp mv \$i.tmp \$i done done for j in \`seq 1 1 \$MAP_COUNT\` do CURRENT=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$1}' /etc/iface_map\` NEW=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$2}' /etc/iface_map\` INTERIM=\`awk -v MATCH=\$j '{if (NR == MATCH) print \$3}' /etc/iface_map\` mv /etc/ifcfg-\$INTERIM /etc/ifcfg-\$NEW for i in /etc/ifcfg-\$NEW /etc/iface_to_activate /etc/network/interfaces do # the double quotes lets us expand the variables sed -e"s/\$INTERIM/\$NEW/g" \$i > \$i.tmp mv \$i.tmp \$i done done < /etc/iface_map exit 0 EOF cat >> $SCRIPTDIR/find_activate_slaves << EOF #!/bin/msh BOND_MASTER=\$1 for j in \`ifconfig -a | awk '/.*Link encap.*/ {print \$1}'\` do MASTER="" . /etc/ifcfg-\$j if [ "\$MASTER" == "\$BOND_MASTER" ] then #this is a slave of the rising interface echo enslaving \$j to \$BOND_MASTER echo +\$j > /sys/class/net/\$BOND_MASTER/bonding/slaves fi done EOF cat >> $SCRIPTDIR/monitor_dd_progress << EOF #!/bin/msh SRC_FILE_SIZE=\`ls -l /proc/vmcore | awk '{print \$5}'\` BLOCK_SIZE=\$1 SRC_FILE_MB=\`dc \$SRC_FILE_SIZE 1048576 / p\` while true do DD_PID=\`ps | grep -v awk | awk '/dd/ {print \$1}'\` if [ -n "\$DD_PID" ] then break fi done while true do sleep 5 if [ ! -d /proc/\$CP_PID ] then break fi kill -SIGUSR1 \$DD_PID CURRENT_SIZE=\`tail -n 1 /tmp/dd_progress_file | sed "s/[^0-9].*//g"\` CURRENT_MB=\`dc \$CURRENT_SIZE \$BLOCK_SIZE \* 1048576 / p\` echo -n -e "Copied \$CURRENT_MB MB / \$SRC_FILE_MB MB\\\r" done rm -f /tmp/dd_progres_file EOF cat >> $SCRIPTDIR/monitor_scp_progress << EOF #!/bin/msh SRC_FILE_SIZE=\`ls -l /proc/vmcore | awk '{print \$5}'\` LOCATION=\$1 REMOTE_FILE=\$2 SRC_FILE_MB=\`dc \$SRC_FILE_SIZE 1048576 / p\` while true do SCP_PID=\`ps | grep -v awk | awk '/scp/ {print \$1}'\` if [ -n "\$SCP_PID" ] then break fi done while true do sleep 5 if [ ! -d /proc/\$SCP_PID ] then break fi SSH_OUTPUT=\`ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no \$LOCATION ls -l \$REMOTE_FILE\` REMOTE_SIZE=\`echo \$SSH_OUTPUT | awk '{print \$5}'\` REMOTE_SIZE_MB=\`dc \$REMOTE_SIZE 1048576 / p\` echo -n -e "Copied \$REMOTE_SIZE_MB MB / \$SRC_FILE_MB MB\\\r" done EOF cat >> $SCRIPTDIR/monitor_cp_progress <> $SCRIPTDIR/handle_event < /sys\$DEVPATH/loading cat "\$DIR/\$FIRMWARE" > /sys\$DEVPATH/data echo 0 > /sys\$DEVPATH/loading exit 0 done EOF #DONT ADD STUFF to SCRIPTDIR PAST HERE for i in `ls $SCRIPTDIR/*` do chmod 755 $i done if [ -e /etc/fstab.sys ]; then inst /etc/fstab.sys "$MNTIMAGE/etc/fstab.sys" fi #build a good passwd file cat >> $MNTIMAGE/etc/passwd << EOF root:x:0:0:root:/root:/bin/bash EOF for MODULE in $MODULES; do if [ -x /usr/bin/strip ]; then /usr/bin/strip -g $verbose $MODULE -o $MNTIMAGE/lib/$(basename $MODULE) else cp $verbose -a $MODULE $MNTIMAGE/lib fi done # mknod'ing the devices instead of copying them works both with and # without devfs... mkdir $MNTIMAGE/dev/mapper mknod $MNTIMAGE/dev/ram0 b 1 0 mknod $MNTIMAGE/dev/ram1 b 1 1 ln -sf ram1 $MNTIMAGE/dev/ram mknod $MNTIMAGE/dev/null c 1 3 mknod $MNTIMAGE/dev/zero c 1 5 mknod $MNTIMAGE/dev/systty c 4 0 for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 ; do mknod $MNTIMAGE/dev/tty$i c 4 $i done for i in 0 1 2 3 ; do mknod $MNTIMAGE/dev/ttyS$i c 4 $(($i + 64)) done mknod $MNTIMAGE/dev/tty c 5 0 mknod $MNTIMAGE/dev/console c 5 1 mknod $MNTIMAGE/dev/ptmx c 5 2 if [ "$(uname -m)" == "ia64" ]; then mknod $MNTIMAGE/dev/efirtc c 10 136 fi # FIXME -- this can really go poorly with clvm or duplicate vg names. # nash should do lvm probing for us and write its own configs. if [ -n "$vg_list" ]; then inst /sbin/lvm "$MNTIMAGE/bin/lvm" bin="$bin /sbin/lvm" if [ -f /etc/lvm/lvm.conf ]; then cp $verbose --parents /etc/lvm/lvm.conf $MNTIMAGE/ fi fi # Firmware, we need to suck it all in, just in case... mkdir -p $MNTIMAGE/lib/firmware cp -r /lib/firmware/* $MNTIMAGE/lib/firmware/ echo -n >| $RCFILE cat >> $MNTIMAGE/init << EOF #!/bin/msh export PATH=$PATH:/scriptfns mount -t proc /proc /proc echo Mounting proc filesystem echo Mounting sysfs filesystem mount -t sysfs /sys /sys echo "/scriptfns/handle_event" > /sys/kernel/uevent_helper echo 1 > /proc/sys/vm/dirty_background_ratio echo 5 > /proc/sys/vm/dirty_ratio echo 10 > /proc/sys/vm/dirty_writeback_centisecs echo 50 > /proc/sys/vm/dirty_expire_centisecs echo Creating /dev mount -o mode=0755 -t tmpfs /dev /dev mkdir /dev/pts mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts mkdir /dev/shm mkdir /dev/mapper echo Creating initial device nodes mknod /dev/null c 1 3 mknod /dev/zero c 1 5 mknod /dev/systty c 4 0 mknod /dev/tty c 5 0 mknod /dev/console c 5 1 mknod /dev/ptmx c 5 2 mknod /dev/rtc c 254 0 mknod /dev/urandom c 1 9 EOF # XXX really we need to openvt too, in case someting changes the # color palette and then changes vts on fbcon before gettys start. # (yay, fbcon bugs!) for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 ; do emit "mknod /dev/tty$i c 4 $i" done for i in 0 1 2 3 ; do emit "mknod /dev/ttyS$i c 4 $(($i + 64))" done emit "mknod /dev/mem c 1 1" for MODULE in $MODULES; do text="" module=`echo $MODULE | sed "s|.*/||" | sed "s/.k\?o$//"` fullmodule=`echo $MODULE | sed "s|.*/||"` options=`sed -n -e "s/^options[ ][ ]*$module[ ][ ]*//p" $modulefile 2>/dev/null` options2=`sed -n -e "s/^options[ ][ ]*$module[ ][ ]*//p" $KDUMP_CONFIG_FILE 2>/dev/null` # Overwrite options if option is specified in kdump.conf if [ -n "$options2" ]; then options=$options2 fi if [ -n "$options" ]; then vecho "Adding module $module$text with options $options" else vecho "Adding module $module$text" fi emit "echo \"Loading $fullmodule module\"" emit "insmod /lib/$fullmodule $options" # Hack - we need a delay after loading usb-storage to give things # time to settle down before we start looking a block devices if [ "$module" = "usb-storage" ]; then emit "echo Waiting 8 seconds for driver initialization." emit "sleep 8" fi if [ "$module" = "zfcp" -a -f /etc/zfcp.conf ]; then emit "echo Waiting 2 seconds for driver initialization." emit "sleep 2" cat /etc/zfcp.conf | grep -v "^#" | tr "A-Z" "a-z" | while read DEVICE SCSIID WWPN SCSILUN FCPLUN; do cemit < /sys/bus/ccw/drivers/zfcp/${DEVICE/0x/}/port_add echo -n $FCPLUN > /sys/bus/ccw/drivers/zfcp/${DEVICE/0x/}/$WWPN/unit_add echo -n 1 > /sys/bus/ccw/drivers/zfcp/${DEVICE/0x/}/online EOF done fi done # Before we create our block devices, we need to make sure that we have all the needed block devices discovered # Thats seems like a chicken and egg problem, I know, but we generated a critcal_disks list when we build this initramfs # that tell us what devices we need to wait to see in /sys/block cat >> $MNTIMAGE/init << EOF echo "Waiting for required block device discovery" timeout_count=0 for i in \`cat /etc/critical_disks\` do echo -n Waiting for \$i... while [ ! -d /sys/block/\$i ] do sleep 1 if [ -n "$DISK_TIMEOUT" -a "\$timeout_count" -ge "$DISK_TIMEOUT" ] then break 2 fi timeout_count=\`expr \$timeout_count + 1\` done echo Found done EOF # HACK: module loading + device creation isn't necessarily synchronous... # this will make sure that we have all of our devices before trying # things like RAID or LVM emit "echo Creating Block Devices" emit "mkdir /dev/cciss" emit "mkdir /dev/ida" emit "for i in \`ls /sys/block\`; do" emit " MAJOR_NUM=\`cat /sys/block/\$i/dev | cut -d":" -f1\`" emit " MINOR_NUM=\`cat /sys/block/\$i/dev | cut -d":" -f2\`" emit " MINOR_RANGE=\`cat /sys/block/\$i/range | cut -d":" -f2\`" emit " PART_SEP=''" emit " i=\`echo \$i | sed 's/\!/\//g'\`" emit " if echo \$i | grep -q '^cciss'; then" emit " PART_SEP='p'" emit " elif echo \$i | grep -q '^ida'; then" emit " PART_SEP='p'" emit " fi" emit " echo Creating block device \$i" emit " mknod /dev/\$i b \$MAJOR_NUM \$MINOR_NUM" emit " if [ \"\$MINOR_RANGE\" -gt 1 ]" emit " then" emit " MINOR_END=\`echo \$MINOR_NUM \$MINOR_RANGE + p | dc\`" emit " MINOR_START=\`echo \$MINOR_NUM 1 + p | dc\`" emit " PART_NUM=1" emit " for j in \`seq \$MINOR_START 1 \$MINOR_END\`" emit " do" emit " if [ ! -e /dev/\$i\$PART_NUM ]" emit " then" emit " mknod /dev/\$i\$PART_SEP\$PART_NUM b \$MAJOR_NUM \$j" emit " fi" emit " PART_NUM=\`expr \$PART_NUM + 1\`" emit " done" emit " fi" emit "done" #now do any software raid devices we might have emit "if [ -f /etc/mdadm.conf ]" emit "then" emit " for i in \`awk '/.*ARRAY.*/{print \$2}' /etc/mdadm.conf\`" emit " do" emit " MD_MIN=\`echo \$i | sed -e's/\(^.*\)\([0-9]\+$\)/\2/'\`" emit " mknod \$i b 9 \$MD_MIN" emit " done" emit "fi" if [ -n "$vg_list" ]; then emit "echo Making device-mapper control node" emit "DM_MAJ=\`cat /proc/devices | grep misc | cut -d\" \" -f2\`" emit "DM_MIN=\`cat /proc/misc | grep device-mapper | cut -d\" \" -f2\`" emit "mknod /dev/mapper/control b \$DM_MAJ \$DM_MIN" fi if [ -n "$net_list" ]; then for netdev in $net_list; do emit "echo Bringing up $netdev" handle_netdev $netdev #emit $network done fi emitdms if [ -n "$raiddevices" ]; then for dev in $raiddevices; do cp -a /dev/${dev} $MNTIMAGE/dev emit "\#need code here to set up md devs" done fi emit "if [ -f /etc/mdadm.conf ]" emit "then" emit " mdadm -A -s" emit "fi" if [ -n "$vg_list" ]; then emit "echo Scanning logical volumes" emit "lvm vgscan --ignorelockingfailure --mknodes" emit "echo Activating logical volumes" emit "lvm vgchange -a y --ignorelockingfailure" emit "DM_NUM=0" emit "for i in \`lvm lvs --noheadings -o lv_name,vg_name | sed -e's/ \\+/:/g'\`" emit "do" emit " LV=\`echo \$i | awk -F\":\" '{ print \$2 }'\`" emit " VGRP=\`echo \$i | awk -F\":\" '{ print \$3 }'\`" emit " mkdir -p /dev/\$VGRP" emit " if [ ! -e /dev/\$VGRP/\$LV ]" emit " then" emit " ln -s /dev/mapper/\$VGRP-\$LV /dev/\$VGRP/\$LV" emit " DM_NUM=\`echo \$DM_NUM 1 + p | dc\`" emit " if [ -z \"\$noresume\" ]" emit " then" emit " /sbin/dmsetup.static resume /dev/mapper/\$VGRP-\$LV" emit " fi" emit " fi" emit "done" fi kdump_chk() { rc=`eval $1` && return $rc echo "$KDUMP_CONFIG_FILE: $2" exit 1 } if [ -n "$KDUMP_CONFIG_FILE" ]; then memtotal=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'` #timezone info for date which outputs YYYY-MM-DD-hh:mm cp /etc/localtime $MNTIMAGE/etc/localtime cp /etc/sysconfig/clock $MNTIMAGE/etc emit ". /etc/clock" emit " if [ \"\$UTC\" == "true" ]" emit " then" emit " TIME_FORMAT=-u" emit " else" emit " TIME_FORMAT=-l" emit "fi" emit "hwclock --hctosys \$TIME_FORMAT" emit "DATE=\`date +%Y-%m-%d-%T\`" bin="$bin /sbin/dmsetup /sbin/kpartx" if [ -n "$CORE_COLLECTOR" ]; then bin="$bin /sbin/makedumpfile" fi #ssh, scp require libraries that aren't found with ldd ARCH=`uname -m` lib=/lib && [ -d "/lib64" -a "$ARCH" != "ppc64" ] && lib=/lib64 k_extras="/$lib/libnss_compat.so.2 /$lib/libnss_files.so.2" #traverse the config file and setup each dump location while read config_opt config_val; do [ -z "$config_opt" ] && continue #skip empty lines [ "`echo $config_opt | grep ^# `" ] && continue #skip comments kdump_chk "test -n \"$config_val\"" "Need a location for $config_opt" case "$config_opt" in \#*) continue;; #skip comments raw) #test raw partition kdump_chk "dd if=$config_val count=1 of=/dev/null > /dev/null 2>&1" \ "Bad raw partition $config_val" #check for available size is greater than $memtotal available_size=$(fdisk -s $config_val) if [ $available_size -lt $memtotal ]; then echo "Warning: There is not space enough to save a vmcore." echo " The size of $config_val should be much greater than $memtotal kilo bytes." fi #setup raw case if [ -n "$KDUMP_PRE" ] then emit "$KDUMP_PRE" emit "if [ \$? -ne 0 ]" emit "then" emit " echo kdump_pre script exited with non-zero status" emit " $FINAL_ACTION" emit "fi" fi emit "echo Saving to partition $config_val" emit "monitor_dd_progress 512 &" if [ -z "$CORE_COLLECTOR" ] then emit "dd if=/proc/vmcore of=$config_val bs=512 >> /tmp/dd_progress_file 2>&1" else CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/\(^makedumpfile\)\(.*$\)/\1 -F \2/'` emit "$CORE_COLLECTOR /proc/vmcore | dd of=$config_val bs=512 >> /tmp/dd_progress_file 2>&1" fi emit "exitcode=\$?" emit "if [ \$exitcode == 0 ]" emit "then" emit " echo -e \"\\\033[0JSaving core complete\"" emit "fi" emit "sync" if [ -x "$KDUMP_POST" ]; then emit "$KDUMP_POST \$exitcode" fi emit "[ \$exitcode == 0 ] && $FINAL_ACTION" ;; net) #build an /etc/passwd for scp to work properly grep "^root" /etc/passwd > $MNTIMAGE/etc/passwd # bring up the network emit "for i in \`ls /etc/ifcfg-*\`" emit "do" emit " NETDEV=\`echo \$i | cut -d\"-\" -f2\`" emit " map_interface \$NETDEV" emit "done" emit "rename_interfaces" emit "IFACE=\`cat /etc/iface_to_activate\`" emit "ifup \$IFACE" #lets make sure we're up emit "IFADDR=\`ifconfig \$IFACE | awk '/inet addr/ {print \$2}' | cut -d\":\" -f 2\`" emit "if [ -z \"\$IFADDR\" ]" emit "then" emit " echo \"\$IFACE failed to come up\"" if [ "$DEFAULT_ACTION" == "shell" ] then emit " echo \"Dropping to shell. exit to reboot\"" emit " /bin/msh" fi emit " $FINAL_ACTION" emit "fi" #grab remote host and xlate into numbers rhost=`echo $config_val | sed 's/.*@//' | cut -d':' -f1` need_dns=`echo $rhost|grep [a-zA-Z]` [ -n "$need_dns" ] && rhost=`getent hosts $rhost|cut -d' ' -f1` #find the local ip being used as a route to remote ip netdev=`/sbin/ip route get to $rhost 2>&1` [ $? != 0 ] && echo "Bad kdump location: $config_val" && exit 1 OFF_SUBNET=`echo $netdev | grep via` if [ -n "$OFF_SUBNET" ] then # we are going to a different subnet lhost=`echo $netdev|awk '{print $7}'|head -n 1` else # we are on the same subnet lhost=`echo $netdev|awk '{print $5}'|head -n 1` fi emit "echo Saving to remote location $config_val" if [ -z "`echo $config_val|grep @`" ]; then #NFS path #test nfs mount and directory creation rlocation=`echo $config_val| sed 's/.*:/'"$rhost"':/'` tmnt=`mktemp -dq` kdump_chk "mount -t nfs -o nolock $rlocation $tmnt" \ "Bad NFS mount $config_val" mkdir -p $tmnt/$SAVE_PATH tdir=`mktemp -dqp $tmnt/$SAVE_PATH` available_size=$(df -P $tdir | tail -1 | tr -s ' ' ':' | cut -d: -f5) rc=$? && rm -rf $tdir umount $tmnt if [ $? != 0 ]; then echo "Cannot unmount the temporary directory" exit 1 fi rm -rf $tmnt if [ $rc != "0" ]; then echo "Cannot create directory in $config_val: $SAVE_PATH" exit 1 fi if [ -z "$CORE_COLLECTOR" ]; then CORE_COLLECTOR="cp" fi #check for available size is greater than $memtotal if [ $available_size -lt $memtotal ]; then echo "Warning: There is not space enough to save a vmcore." echo " The size of $config_val should be much greater than $memtotal kilo bytes." fi #setup nfs case if [ -n "$KDUMP_PRE" ] then emit "$KDUMP_PRE" emit "if [ \$? -ne 0 ]" emit "then" emit " echo kdump_pre script exited with non-zero status" emit " $FINAL_ACTION" emit "fi" fi mkdir -p $MNTIMAGE/mnt emit "mount -t nfs -o nolock $rlocation /mnt" emit "if [ \$? == 0 ]" emit "then" emit " mkdir -p /mnt/$SAVE_PATH/$lhost-\$DATE" emit " VMCORE=/mnt/$SAVE_PATH/$lhost-\$DATE/vmcore" emit " export VMCORE" emit " monitor_cp_progress \$VMCORE-incomplete &" emit " $CORE_COLLECTOR /proc/vmcore \$VMCORE-incomplete >/dev/null" emit " exitcode=\$?" emit " if [ \$exitcode == 0 ]" emit " then" emit " mv \$VMCORE-incomplete \$VMCORE" emit " echo -e \"\\\033[0JSaving core complete\"" emit " fi" if [ -x "$KDUMP_POST" ]; then emit " $KDUMP_POST \$exitcode" fi emit " umount /mnt" emit " [ \$exitcode == 0 ] && $FINAL_ACTION" emit "fi" else #SSH path #rebuild $config_val replacing machine name with ip address if [ -n "$CORE_COLLECTOR" ] then CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e's/\(^makedumpfile\)\(.*$\)/\1 -F \2/'` fi bin="$bin /usr/bin/ssh /usr/bin/scp" rlocation=`echo $config_val|sed 's/@.*/@'"$rhost"'/'` #test ssh path and directory creation s_opts="-o BatchMode=yes -o StrictHostKeyChecking=no" kdump_chk "ssh -q $s_opts $rlocation mkdir -p $SAVE_PATH $SAVE_PATH/$lhost-\$DATE/vmcore-incomplete\"" fi emit "exitcode=\$?" emit "if [ \$exitcode == 0 ]" emit "then" if [ -z "$CORE_COLLECTOR" ] then emit " ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mv \$VMCORE-incomplete \$VMCORE" else emit " ssh -q -o BatchMode=yes -o StrictHostKeyChecking=no $rlocation mv \$VMCORE-incomplete \$VMCORE.flat" fi emit " echo -e \"\\\033[0JSaving core complete\"" emit "fi" if [ -x "$KDUMP_POST" ]; then emit "$KDUMP_POST \$exitcode" fi emit "[ \$exitcode == 0 ] && $FINAL_ACTION" fi ;; core_collector) ;; kdump_pre) ;; kdump_post) ;; extra_bins) ;; extra_modules) ;; disk_timeout) ;; blacklist) ;; options) ;; default) ;; link_delay) ;; path) ;; *) #test filesystem and directory creation kdump_chk "test -f /sbin/fsck.$config_opt" "Unsupported type $config_opt" tmnt=`mktemp -dq` kdump_chk "mount -t $config_opt $config_val $tmnt" "Bad mount point $config_val" mkdir -p $tmnt/$SAVE_PATH tdir=`mktemp -dqp $tmnt/$SAVE_PATH` rc=$? available_size=$(df $tdir | tail -1 | tr -s ' ' ':' | cut -d: -f4) rm -rf $tdir > /dev/null 2>&1 umount $tmnt > /dev/null 2>&1 if [ $rc != "0" ]; then echo "Cannot create directory in $config_val: $SAVE_PATH" exit 1 fi #check for available size is greater than $memtotal if [ $available_size -lt $memtotal ]; then echo "Warning: There is not space enough to save a vmcore." echo " The size of $config_val should be much greater than $memtotal kilo bytes." fi #setup filesystem case if [ -n "$KDUMP_PRE" ] then emit "$KDUMP_PRE" emit "if [ \$? -ne 0 ]" emit "then" emit " echo kdump_pre script exited with non-zero status" emit " $FINAL_ACTION" emit "fi" fi mkdir -p $MNTIMAGE/mnt touch $MNTIMAGE/etc/mtab if [ -z "$CORE_COLLECTOR" ]; then CORE_COLLECTOR="cp" fi emit "echo Saving to the local filesystem $config_val" emit "DUMPDEV=$config_val" emit "IS_LABEL=\`echo \$DUMPDEV | grep LABEL\`" emit "IS_UUID=\`echo \$DUMPDEV | grep UUID\`" emit "if [ -n \"\$IS_LABEL\" -o -n \"\$IS_UUID\" ] " emit "then" emit " DUMPDEV=\`findfs \$DUMPDEV\`" emit "fi" emit "fsck.$config_opt -y \$DUMPDEV" emit "mount -t $config_opt \$DUMPDEV /mnt" emit "if [ \$? == 0 ]" emit "then" emit " mkdir -p /mnt/$SAVE_PATH/127.0.0.1-\$DATE" emit " VMCORE=/mnt/$SAVE_PATH/127.0.0.1-\$DATE/vmcore" emit " export VMCORE" if [ "$CORE_COLLECTOR" == "cp" ]; then emit " monitor_cp_progress \$VMCORE-incomplete &" fi emit " $CORE_COLLECTOR /proc/vmcore \$VMCORE-incomplete >/dev/null" emit " exitcode=\$?" emit " if [ \$exitcode == 0 ]" emit " then" emit " mv \$VMCORE-incomplete \$VMCORE" emit " echo -e \"\\\033[0JSaving core complete\"" emit " fi" emit " sync" if [ -x "$KDUMP_POST" ]; then emit " $KDUMP_POST \$exitcode" fi emit "fi" emit "umount /mnt" emit "[ \$exitcode == 0 ] && $FINAL_ACTION" ;; esac done < $KDUMP_CONFIG_FILE #now handle the default action if [ "$DEFAULT_ACTION" == "shell" ] then emit "echo dropping to initramfs shell" emit "echo exiting this shell will reboot your system" emit "/bin/msh" fi case $DEFAULT_ACTION in reboot|halt|poweroff|shell) emit "$FINAL_ACTION" ;; *) emit "echo Attempting to enter user-space to capture vmcore" ;; esac #find the shared libraries. this snippet taken from kboot TEMPLDCFG=`mktemp` for lib in `ls /etc/ld.so.conf.d/* 2>/dev/null | grep -v kernelcap` do echo "include " $lib >> $TEMPLDCFG done /sbin/ldconfig -f $TEMPLDCFG kdump_libs=`for n in $bin; do ldd "$n" 2>/dev/null | tr -s '\011' ' ' | sed 's/.*=> *//;s/^ *//;/ *(0x.*)/s///p;d' done | sort | uniq | sed '/^ *$/d'` /sbin/ldconfig rm -f $TEMPLDCFG #copy the binaries and their shared libraries to the archive for n in $bin $kdump_libs $k_extras; do mkdir -p $MNTIMAGE/`dirname $n` cp $n $MNTIMAGE/$n done fi emit "echo Creating root device." emit "#check to see if we have root= on the command line" emit "ROOTDEV=\`cat /proc/cmdline | grep root=\`" emit "if [ -n \"\$ROOTDEV\" ]" emit "then" emit " ROOTDEV=\`cat /proc/cmdline | sed 's/^.*root=//' | cut -d\" \" -f1\`" emit " IS_LABEL=\`echo \$ROOTDEV | grep LABEL\`" emit " IS_UUID=\`echo \$ROOTDEV | grep UUID\`" emit " if [ -n \"\$IS_LABEL\" -o -n \"\$IS_UUID\" ] " emit " then" emit " ROOTDEV=\`findfs \$ROOTDEV\`" emit " fi" emit "else" emit " #we need to get the root major/minor from real-root-dev" emit " ROOT_DEV_NR=\`cat /proc/sys/kernel/real-root-dev\`" emit " ROOT_MIN=\`echo \$ROOT_DEV_NR | sed -e's/\\([0-9a-f]\\{1,2\\}\\)\\([0-9a-f]\\{2\\}\\)/\\2/'\`" emit " ROOT_MAJ=\`echo \$ROOT_DEV_NR | sed -e's/\\([0-9a-f]\\{1,2\\}\\)\\([0-9a-f]\\{2\\}\\)/\\1/'\`" emit " mknod /dev/rootdev b 0x\$ROOT_MAJ 0x\$ROOT_MIN" emit " ROOTDEV=/dev/rootdev" emit "fi" emit "echo Checking root filesystem." emit "fsck -y \$ROOTDEV" emit "echo Mounting root filesystem: mount -t $rootfs \$ROOTDEV /sysroot" emit "mount -t $rootfs \$ROOTDEV /sysroot >/dev/null 2>&1 " emit "if [ \$? != 0 ]" emit "then" emit " echo unable to mount rootfs. Dropping to shell" emit " /bin/msh" emit "fi" emit "#move various filesystems and prime the rootfs to boot properly" emit "umount /proc" emit "mount -t proc proc /sysroot/proc" emit "umount /sys" emit "mount -t sysfs sysfs /sysroot/sys" emit "mount -o bind /dev /sysroot/dev" if [ -f $MNTIMAGE/etc/blacklist-kdump.conf ] ; then emit "tdir=\`mktemp -d\`" emit "mkdir -p \$tdir" emit "cp -r /sysroot/etc/modprobe.d/* \$tdir/" emit "mount -t ramfs ramfs /sysroot/etc/modprobe.d" emit "cp -r \$tdir/* /sysroot/etc/modprobe.d/" emit "cp /etc/blacklist-kdump.conf /sysroot/etc/modprobe.d/" fi emit "touch /sysroot/fastboot" emit "echo Switching to new root and running init." emit "exec switch_root /sysroot /sbin/init" # END OF INIT SCRIPT chmod +x $RCFILE (cd $MNTIMAGE; find | cpio --quiet -c -o) >| $IMAGE || exit 1 if [ -n "$compress" ]; then gzip -9 < $IMAGE >| $target || rc=1 else cp -a $IMAGE $target || rc=1 fi rm -rf $MNTIMAGE $IMAGE $TMPDISKLIST if [ -n "$MNTPOINT" ]; then rm -rf $MNTPOINT ; fi exit $rc