1*86d7f5d3SJohn Marino#!/bin/bash
2*86d7f5d3SJohn Marino#
3*86d7f5d3SJohn Marino# lvm2create_initrd
4*86d7f5d3SJohn Marino#
5*86d7f5d3SJohn Marino# Miguel Cabeca
6*86d7f5d3SJohn Marino# cabeca (at) ist (dot) utl (dot) pt
7*86d7f5d3SJohn Marino#
8*86d7f5d3SJohn Marino# Inspiration to write this script came from various sources
9*86d7f5d3SJohn Marino#
10*86d7f5d3SJohn Marino# Original LVM lvmcreate_initrd: ftp://ftp.sistina.com/pub/LVM/1.0/
11*86d7f5d3SJohn Marino# Kernel initrd.txt: http://www.kernel.org/
12*86d7f5d3SJohn Marino# EVMS INSTALL.initrd & linuxrc: http://evms.sourceforge.net/
13*86d7f5d3SJohn Marino# Jeffrey Layton's lvm2create_initrd: http://poochiereds.net/svn/lvm2create_initrd/
14*86d7f5d3SJohn Marino# Christophe Saout's initrd & linuxrc: http://www.saout.de/misc/
15*86d7f5d3SJohn Marino#
16*86d7f5d3SJohn Marino# This script was only tested with kernel 2.6 with everything required to boot
17*86d7f5d3SJohn Marino# the root filesystem built-in (not as modules). Ex: SCSI or IDE, RAID, device mapper
18*86d7f5d3SJohn Marino# It does not support devfs as it is deprecated in the 2.6 kernel series
19*86d7f5d3SJohn Marino#
20*86d7f5d3SJohn Marino# It needs lvm2 tools, busybox, pivot_root, MAKEDEV
21*86d7f5d3SJohn Marino#
22*86d7f5d3SJohn Marino# It has been tested on Debian sid (unstable) only
23*86d7f5d3SJohn Marino#
24*86d7f5d3SJohn Marino# Changelog
25*86d7f5d3SJohn Marino# 26/02/2004	Initial release -- Miguel Cabeca
26*86d7f5d3SJohn Marino# 27/02/2004	Removed the BUSYBOXSYMLINKS var. The links are now determined at runtime.
27*86d7f5d3SJohn Marino#		some changes in init script to call a shell if something goes wrong. -- Miguel Cabeca
28*86d7f5d3SJohn Marino# 19/04/2004    Several small changes. Pass args to init so single user mode works. Add some
29*86d7f5d3SJohn Marino#               PATH entries to /sbin/init shell script so chroot works without /usr mounted. Remove
30*86d7f5d3SJohn Marino#               mkdir /initrd so we don't cause problems if root filesystem is corrupted. -- Jeff Layton
31*86d7f5d3SJohn Marino# 15/05/2004	initial support for modules, create lvm.conf from lvm dumpconfig, other cleanups -- Jeff Layton
32*86d7f5d3SJohn Marino# 14/11/2006	Update handling of ldd output to handle hardcoded library links and virtual dll linux-gate.
33*86d7f5d3SJohn Marino#		Add support for Gentoo-style MAKEDEV. Remove hardcoded BINUTILS paths -- Douglas Mayle
34*86d7f5d3SJohn Marino#
35*86d7f5d3SJohn Marino# Copyright Miguel Cabeca, Jeffrey Layton, 2004
36*86d7f5d3SJohn Marino#
37*86d7f5d3SJohn Marino#    This program is free software; you can redistribute it and/or modify
38*86d7f5d3SJohn Marino#    it under the terms of the GNU General Public License as published by
39*86d7f5d3SJohn Marino#    the Free Software Foundation; either version 2 of the License, or
40*86d7f5d3SJohn Marino#    (at your option) any later version.
41*86d7f5d3SJohn Marino#
42*86d7f5d3SJohn Marino#    This program is distributed in the hope that it will be useful,
43*86d7f5d3SJohn Marino#    but WITHOUT ANY WARRANTY; without even the implied warranty of
44*86d7f5d3SJohn Marino#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45*86d7f5d3SJohn Marino#    GNU General Public License for more details.
46*86d7f5d3SJohn Marino#
47*86d7f5d3SJohn Marino#    You should have received a copy of the GNU General Public License
48*86d7f5d3SJohn Marino#    along with this program; if not, write to the Free Software
49*86d7f5d3SJohn Marino#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
50*86d7f5d3SJohn Marino#
51*86d7f5d3SJohn Marino# $Id: lvm2create_initrd,v 1.1.1.1 2008/12/22 00:18:58 haad Exp $
52*86d7f5d3SJohn Marino
53*86d7f5d3SJohn MarinoTMPMNT=/tmp/mnt.$$
54*86d7f5d3SJohn MarinoDEVRAM=/tmp/initrd.$$
55*86d7f5d3SJohn Marino
56*86d7f5d3SJohn Marino# set defaults
57*86d7f5d3SJohn MarinoBINFILES=${BINFILES:-"`which lvm` `which bash` `which busybox` `which pivot_root`"}
58*86d7f5d3SJohn MarinoBASICDEVICES=${BASICDEVICES:-"std consoleonly fd"}
59*86d7f5d3SJohn MarinoBLOCKDEVICES=${BLOCKDEVICES:-"md hda hdb hdc hdd sda sdb sdc sdd"}
60*86d7f5d3SJohn MarinoMAKEDEV=${MAKEDEV:-"debian"}
61*86d7f5d3SJohn Marino
62*86d7f5d3SJohn Marino# Uncomment this if you want to disable automatic size detection
63*86d7f5d3SJohn Marino#INITRDSIZE=4096
64*86d7f5d3SJohn Marino
65*86d7f5d3SJohn MarinoPATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH
66*86d7f5d3SJohn Marino
67*86d7f5d3SJohn Marinousage () {
68*86d7f5d3SJohn Marino	echo "Create an initial ramdisk image for LVM2 root filesystem"
69*86d7f5d3SJohn Marino	echo "$cmd: [-h] [-v] [-c lvm.conf] [-m modulelist] [-e extrafiles] -r [raiddevs] [-R mdadm.conf] [-M style] [kernel version]"
70*86d7f5d3SJohn Marino	echo "      -h|--help      print this usage message"
71*86d7f5d3SJohn Marino	echo "      -v|--verbose   verbose progress messages"
72*86d7f5d3SJohn Marino	echo "      -c|--lvmconf   path to lvm.conf (/etc/lvm/lvm.conf)"
73*86d7f5d3SJohn Marino	echo "      -m|--modules   modules to copy to initrd image"
74*86d7f5d3SJohn Marino	echo "      -e|--extra     extra files to add to initrd"
75*86d7f5d3SJohn Marino	echo "      -r|--raid      raid devices to start in initrd"
76*86d7f5d3SJohn Marino	echo "      -R|--raidconf  location of mdadm.conf file to include"
77*86d7f5d3SJohn Marino	echo "      -M|--makedev   set MAKEDEV type (debian or redhat)"
78*86d7f5d3SJohn Marino}
79*86d7f5d3SJohn Marino
80*86d7f5d3SJohn Marinoverbose () {
81*86d7f5d3SJohn Marino   [ "$VERBOSE" ] && echo "`echo $cmd | tr '[a-z0-9/_]' ' '` -- $1" || true
82*86d7f5d3SJohn Marino}
83*86d7f5d3SJohn Marino
84*86d7f5d3SJohn Marinocleanup () {
85*86d7f5d3SJohn Marino  [ "`mount | grep $DEVRAM`" ] && verbose "unmounting $DEVRAM" && umount $DEVRAM
86*86d7f5d3SJohn Marino  [ -f $DEVRAM ] && verbose "removing $DEVRAM" && rm $DEVRAM
87*86d7f5d3SJohn Marino  [ -d $TMPMNT ] && verbose "removing $TMPMNT" && rmdir $TMPMNT
88*86d7f5d3SJohn Marino  verbose "exit with code $1"
89*86d7f5d3SJohn Marino  exit $1
90*86d7f5d3SJohn Marino}
91*86d7f5d3SJohn Marino
92*86d7f5d3SJohn Marinotrap "
93*86d7f5d3SJohn Marino  verbose 'Caught interrupt'
94*86d7f5d3SJohn Marino  echo 'Bye bye...'
95*86d7f5d3SJohn Marino  cleanup 1
96*86d7f5d3SJohn Marino" 1 2 3 15
97*86d7f5d3SJohn Marino
98*86d7f5d3SJohn Marinocreate_init () {
99*86d7f5d3SJohn Marino   cat << 'INIT' > $TMPMNT/sbin/init
100*86d7f5d3SJohn Marino#!/bin/bash
101*86d7f5d3SJohn Marino
102*86d7f5d3SJohn Marino# include in the path some dirs from the real root filesystem
103*86d7f5d3SJohn Marino# for chroot, blockdev
104*86d7f5d3SJohn MarinoPATH="/sbin:/bin:/usr/sbin:/usr/bin:/lib/lvm-200:/initrd/bin:/initrd/sbin"
105*86d7f5d3SJohn MarinoPRE="initrd:"
106*86d7f5d3SJohn Marino
107*86d7f5d3SJohn Marinodo_shell(){
108*86d7f5d3SJohn Marino    /bin/echo
109*86d7f5d3SJohn Marino    /bin/echo "*** Entering LVM2 rescue shell. Exit shell to continue booting. ***"
110*86d7f5d3SJohn Marino    /bin/echo
111*86d7f5d3SJohn Marino    /bin/bash
112*86d7f5d3SJohn Marino}
113*86d7f5d3SJohn Marino
114*86d7f5d3SJohn Marinoecho "$PRE Remounting / read/write"
115*86d7f5d3SJohn Marinomount -t ext2 -o remount,rw /dev/ram0 /
116*86d7f5d3SJohn Marino
117*86d7f5d3SJohn Marino
118*86d7f5d3SJohn Marino# We need /proc for device mapper
119*86d7f5d3SJohn Marinoecho "$PRE Mounting /proc"
120*86d7f5d3SJohn Marinomount -t proc none /proc
121*86d7f5d3SJohn Marino
122*86d7f5d3SJohn Marino# plug in modules listed in /etc/modules
123*86d7f5d3SJohn Marinoif [ -f /etc/modules ]; then
124*86d7f5d3SJohn Marino    echo -n "$PRE plugging in kernel modules:"
125*86d7f5d3SJohn Marino    cat /etc/modules |
126*86d7f5d3SJohn Marino    while read module; do
127*86d7f5d3SJohn Marino        echo -n " $module"
128*86d7f5d3SJohn Marino        modprobe $module
129*86d7f5d3SJohn Marino    done
130*86d7f5d3SJohn Marino    echo '.'
131*86d7f5d3SJohn Marinofi
132*86d7f5d3SJohn Marino
133*86d7f5d3SJohn Marino# start raid devices if raid_autostart file exists
134*86d7f5d3SJohn Marinoif [ -f /etc/raid_autostart ]; then
135*86d7f5d3SJohn Marino    if [ ! -f /etc/mdadm/mdadm.conf ]; then
136*86d7f5d3SJohn Marino        mdoptions='--super-minor=dev'
137*86d7f5d3SJohn Marino    fi
138*86d7f5d3SJohn Marino    cat /etc/raid_autostart|
139*86d7f5d3SJohn Marino    while read dev; do
140*86d7f5d3SJohn Marino    	echo "Starting RAID device $dev"
141*86d7f5d3SJohn Marino        /sbin/mdadm --assemble $dev $mdoptions
142*86d7f5d3SJohn Marino    done
143*86d7f5d3SJohn Marinofi
144*86d7f5d3SJohn Marino
145*86d7f5d3SJohn Marino# Create the /dev/mapper/control device for the ioctl
146*86d7f5d3SJohn Marino# interface using the major and minor numbers that have been allocated
147*86d7f5d3SJohn Marino# dynamically.
148*86d7f5d3SJohn Marino
149*86d7f5d3SJohn Marinoecho -n "$PRE Finding device mapper major and minor numbers "
150*86d7f5d3SJohn Marino
151*86d7f5d3SJohn MarinoMAJOR=$(sed -n 's/^ *\([0-9]\+\) \+misc$/\1/p' /proc/devices)
152*86d7f5d3SJohn MarinoMINOR=$(sed -n 's/^ *\([0-9]\+\) \+device-mapper$/\1/p' /proc/misc)
153*86d7f5d3SJohn Marinoif test -n "$MAJOR" -a -n "$MINOR" ; then
154*86d7f5d3SJohn Marino	mkdir -p -m 755 /dev/mapper
155*86d7f5d3SJohn Marino	mknod -m 600 /dev/mapper/control c $MAJOR $MINOR
156*86d7f5d3SJohn Marinofi
157*86d7f5d3SJohn Marino
158*86d7f5d3SJohn Marinoecho "($MAJOR,$MINOR)"
159*86d7f5d3SJohn Marino
160*86d7f5d3SJohn Marino# Device-Mapper dynamically allocates all device numbers. This means it is possible
161*86d7f5d3SJohn Marino# that the root volume specified to LILO or Grub may have a different number when the
162*86d7f5d3SJohn Marino# initrd runs than when the system was last running. In order to make sure the
163*86d7f5d3SJohn Marino# correct volume is mounted as root, the init script must determine what the
164*86d7f5d3SJohn Marino# desired root volume name is by getting the LVM2 root volume name from the kernel command line. In order for
165*86d7f5d3SJohn Marino# this to work correctly, "lvm2root=/dev/Volume_Group_Name/Root_Volume_Name" needs to be passed
166*86d7f5d3SJohn Marino# to the kernel command line (where Root_Volume_Name is replaced by your actual
167*86d7f5d3SJohn Marino# root volume's name.
168*86d7f5d3SJohn Marinofor arg in `cat /proc/cmdline`; do
169*86d7f5d3SJohn Marino	echo $arg | grep '^lvm2root=' > /dev/null
170*86d7f5d3SJohn Marino	if [ $? -eq 0 ]; then
171*86d7f5d3SJohn Marino		rootvol=${arg#lvm2root=}
172*86d7f5d3SJohn Marino		break
173*86d7f5d3SJohn Marino	fi
174*86d7f5d3SJohn Marinodone
175*86d7f5d3SJohn Marino
176*86d7f5d3SJohn Marinoecho "$PRE Activating LVM2 volumes"
177*86d7f5d3SJohn Marino
178*86d7f5d3SJohn Marino
179*86d7f5d3SJohn Marino# run a shell if we're passed lvm2rescue on commandline
180*86d7f5d3SJohn Marinogrep lvm2rescue /proc/cmdline 1>/dev/null 2>&1
181*86d7f5d3SJohn Marinoif [ $? -eq 0 ]; then
182*86d7f5d3SJohn Marino    lvm vgchange --ignorelockingfailure -P -a y
183*86d7f5d3SJohn Marino    do_shell
184*86d7f5d3SJohn Marinoelse
185*86d7f5d3SJohn Marino    lvm vgchange --ignorelockingfailure -a y
186*86d7f5d3SJohn Marinofi
187*86d7f5d3SJohn Marino
188*86d7f5d3SJohn Marinoecho "$PRE Mounting root filesystem $rootvol ro"
189*86d7f5d3SJohn Marinomkdir /rootvol
190*86d7f5d3SJohn Marinoif ! mount -t auto -o ro $rootvol /rootvol; then
191*86d7f5d3SJohn Marino	echo "\t*FAILED*";
192*86d7f5d3SJohn Marino	do_shell
193*86d7f5d3SJohn Marinofi
194*86d7f5d3SJohn Marino
195*86d7f5d3SJohn Marinoecho "$PRE Umounting /proc"
196*86d7f5d3SJohn Marinoumount /proc
197*86d7f5d3SJohn Marino
198*86d7f5d3SJohn Marinoecho "$PRE Changing roots"
199*86d7f5d3SJohn Marinocd /rootvol
200*86d7f5d3SJohn Marinoif ! pivot_root . initrd ; then
201*86d7f5d3SJohn Marino	echo "\t*FAILED*"
202*86d7f5d3SJohn Marino	do_shell
203*86d7f5d3SJohn Marinofi
204*86d7f5d3SJohn Marino
205*86d7f5d3SJohn Marinoecho "$PRE Proceeding with boot..."
206*86d7f5d3SJohn Marino
207*86d7f5d3SJohn Marinoexec chroot . /bin/sh -c "umount /initrd; blockdev --flushbufs /dev/ram0 ; exec /sbin/init $*" < dev/console > dev/console 2>&1
208*86d7f5d3SJohn Marino
209*86d7f5d3SJohn MarinoINIT
210*86d7f5d3SJohn Marino   chmod 555 $TMPMNT/sbin/init
211*86d7f5d3SJohn Marino}
212*86d7f5d3SJohn Marino
213*86d7f5d3SJohn Marino# create lvm.conf file from dumpconfig. Just use filter options
214*86d7f5d3SJohn Marinocreate_lvmconf () {
215*86d7f5d3SJohn Marino    echo 'devices {' > $TMPMNT/etc/lvm/lvm.conf
216*86d7f5d3SJohn Marino    lvm dumpconfig | grep 'filter=' >> $TMPMNT/etc/lvm/lvm.conf
217*86d7f5d3SJohn Marino    echo '}' >> $TMPMNT/etc/lvm/lvm.conf
218*86d7f5d3SJohn Marino}
219*86d7f5d3SJohn Marino
220*86d7f5d3SJohn Marino#
221*86d7f5d3SJohn Marino# Main
222*86d7f5d3SJohn Marino#
223*86d7f5d3SJohn Marino
224*86d7f5d3SJohn Marinocmd=`basename $0`
225*86d7f5d3SJohn Marino
226*86d7f5d3SJohn MarinoVERSION=`uname -r`
227*86d7f5d3SJohn Marino
228*86d7f5d3SJohn Marinowhile [ $# -gt 0 ]; do
229*86d7f5d3SJohn Marino   case $1 in
230*86d7f5d3SJohn Marino   -h|--help) usage; exit 0;;
231*86d7f5d3SJohn Marino   -v|--verbose)  VERBOSE="y";;
232*86d7f5d3SJohn Marino   -c|--lvmconf)  LVMCONF=$2; shift;;
233*86d7f5d3SJohn Marino   -m|--modules)  MODULES=$2; shift;;
234*86d7f5d3SJohn Marino   -e|--extra)    EXTRAFILES=$2; shift;;
235*86d7f5d3SJohn Marino   -r|--raid)     RAID=$2; shift;;
236*86d7f5d3SJohn Marino   -R|--raidconf) RAIDCONF=$2; shift;;
237*86d7f5d3SJohn Marino   -M|--makedev)  MAKEDEV=$2; shift;;
238*86d7f5d3SJohn Marino   [2-9].[0-9]*.[0-9]*) VERSION=$1;;
239*86d7f5d3SJohn Marino   *) echo "$cmd -- invalid option '$1'"; usage; exit 0;;
240*86d7f5d3SJohn Marino   esac
241*86d7f5d3SJohn Marino   shift
242*86d7f5d3SJohn Marinodone
243*86d7f5d3SJohn Marino
244*86d7f5d3SJohn MarinoINITRD=${INITRD:-"/boot/initrd-lvm2-$VERSION.gz"}
245*86d7f5d3SJohn Marino
246*86d7f5d3SJohn Marinoecho "$cmd -- make LVM initial ram disk $INITRD"
247*86d7f5d3SJohn Marinoecho ""
248*86d7f5d3SJohn Marino
249*86d7f5d3SJohn Marinoif [ -n "$RAID" ]; then
250*86d7f5d3SJohn Marino    BINFILES="$BINFILES /sbin/mdadm"
251*86d7f5d3SJohn Marino    RAIDCONF=${RAIDCONF:-"/etc/mdadm/mdadm.conf"}
252*86d7f5d3SJohn Marino    if [ -r $RAIDCONF ]; then
253*86d7f5d3SJohn Marino	EXTRAFILES="$EXTRAFILES $RAIDCONF"
254*86d7f5d3SJohn Marino    else
255*86d7f5d3SJohn Marino        echo "$cmd -- WARNING: No $RAIDCONF! Your RAID device minor numbers must match their superblock values!"
256*86d7f5d3SJohn Marino    fi
257*86d7f5d3SJohn Marinofi
258*86d7f5d3SJohn Marino
259*86d7f5d3SJohn Marino# add modprobe if we declared any modules
260*86d7f5d3SJohn Marinoif [ -n "$MODULES" ]; then
261*86d7f5d3SJohn Marino    BINFILES="$BINFILES /sbin/modprobe /sbin/insmod /sbin/rmmod"
262*86d7f5d3SJohn Marinofi
263*86d7f5d3SJohn Marino
264*86d7f5d3SJohn Marinofor a in $BINFILES $EXTRAFILES; do
265*86d7f5d3SJohn Marino    if [ ! -r "$a" ] ; then
266*86d7f5d3SJohn Marino	echo "$cmd -- ERROR: you need $a"
267*86d7f5d3SJohn Marino	exit 1;
268*86d7f5d3SJohn Marino    fi;
269*86d7f5d3SJohn Marinodone
270*86d7f5d3SJohn Marino
271*86d7f5d3SJohn Marino# Figure out which shared libraries we actually need in our initrd
272*86d7f5d3SJohn Marinoecho "$cmd -- finding required shared libraries"
273*86d7f5d3SJohn Marinoverbose "BINFILES: `echo $BINFILES`"
274*86d7f5d3SJohn Marino
275*86d7f5d3SJohn Marino# We need to strip certain lines from ldd output.  This is the full output of an example ldd:
276*86d7f5d3SJohn Marino#lvmhost~ # ldd /sbin/lvm /bin/bash
277*86d7f5d3SJohn Marino#/sbin/lvm:
278*86d7f5d3SJohn Marino#        not a dynamic executable
279*86d7f5d3SJohn Marino#/bin/bash:
280*86d7f5d3SJohn Marino#        linux-gate.so.1 =>  (0xbfffe000)
281*86d7f5d3SJohn Marino#        libncurses.so.5 => /lib/libncurses.so.5 (0xb7ee3000)
282*86d7f5d3SJohn Marino#        libdl.so.2 => /lib/libdl.so.2 (0xb7edf000)
283*86d7f5d3SJohn Marino#        libc.so.6 => /lib/libc.so.6 (0xb7dc1000)
284*86d7f5d3SJohn Marino#        /lib/ld-linux.so.2 (0xb7f28000)
285*86d7f5d3SJohn Marino#
286*86d7f5d3SJohn Marino# 1) Lines with a ":" contain the name of the original binary we're examining, and so are unnecessary.
287*86d7f5d3SJohn Marino#    We need to strip them because they contain "/", and can be confused with links with a hardcoded path.
288*86d7f5d3SJohn Marino# 2) The linux-gate library is a virtual dll that does not exist on disk, but is instead loaded automatically
289*86d7f5d3SJohn Marino#    into the process space, and can't be copied to the ramdisk
290*86d7f5d3SJohn Marino#
291*86d7f5d3SJohn Marino# After these lines have been stripped, we're interested in the lines remaining if they
292*86d7f5d3SJohn Marino# 1) Contain "=>" because they are pathless links, and the value following the token is the path on the disk
293*86d7f5d3SJohn Marino# 2) Contain "/" because it's a link with a hardcoded path, and so we're interested in the link itself.
294*86d7f5d3SJohn MarinoLIBFILES=`ldd $BINFILES 2>/dev/null |grep -v -E \(linux-gate\|:\) | awk '{if (/=>/) { print $3 } else if (/\//) { print $1 }}' | sort -u`
295*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
296*86d7f5d3SJohn Marino   echo "$cmd -- ERROR figuring out needed shared libraries"
297*86d7f5d3SJohn Marino   exit 1
298*86d7f5d3SJohn Marinofi
299*86d7f5d3SJohn Marino
300*86d7f5d3SJohn Marinoverbose "Shared libraries needed: `echo $LIBFILES`"
301*86d7f5d3SJohn Marino
302*86d7f5d3SJohn MarinoINITRDFILES="$BINFILES $LIBFILES $MODULES $EXTRAFILES"
303*86d7f5d3SJohn Marino
304*86d7f5d3SJohn Marino# tack on stuff for modules if we declared any and the files exist
305*86d7f5d3SJohn Marinoif [ -n "$MODULES" ]; then
306*86d7f5d3SJohn Marino    if [ -f "/etc/modprobe.conf" ]; then
307*86d7f5d3SJohn Marino	INITRDFILES="$INITRDFILES /etc/modprobe.conf"
308*86d7f5d3SJohn Marino    fi
309*86d7f5d3SJohn Marino    if [ -f "/lib/modules/modprobe.conf" ]; then
310*86d7f5d3SJohn Marino	INITRDFILES="$INITRDFILES /lib/modules/modprobe.conf"
311*86d7f5d3SJohn Marino    fi
312*86d7f5d3SJohn Marinofi
313*86d7f5d3SJohn Marino
314*86d7f5d3SJohn Marino# Calculate the the size of the ramdisk image.
315*86d7f5d3SJohn Marino# Don't forget that inodes take up space too, as does the filesystem metadata.
316*86d7f5d3SJohn Marinoecho "$cmd -- calculating initrd filesystem parameters"
317*86d7f5d3SJohn Marinoif [ -z "$INITRDSIZE" ]; then
318*86d7f5d3SJohn Marino   echo "$cmd -- calculating loopback file size"
319*86d7f5d3SJohn Marino   verbose "finding size"
320*86d7f5d3SJohn Marino   INITRDSIZE="`du -Lck $INITRDFILES | tail -1 | cut -f 1`"
321*86d7f5d3SJohn Marino   verbose "minimum: $INITRDSIZE kB for files + inodes + filesystem metadata"
322*86d7f5d3SJohn Marino   INITRDSIZE=`expr $INITRDSIZE + 512`  # enough for ext2 fs + a bit
323*86d7f5d3SJohn Marinofi
324*86d7f5d3SJohn Marino
325*86d7f5d3SJohn Marinoecho "$cmd -- making loopback file ($INITRDSIZE kB)"
326*86d7f5d3SJohn Marinoverbose "using $DEVRAM as a temporary loopback file"
327*86d7f5d3SJohn Marinodd if=/dev/zero of=$DEVRAM count=$INITRDSIZE bs=1024 > /dev/null 2>&1
328*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
329*86d7f5d3SJohn Marino   echo "$cmd -- ERROR creating loopback file"
330*86d7f5d3SJohn Marino   cleanup 1
331*86d7f5d3SJohn Marinofi
332*86d7f5d3SJohn Marino
333*86d7f5d3SJohn Marinoecho "$cmd -- making ram disk filesystem"
334*86d7f5d3SJohn Marinoverbose "mke2fs -F -m0 -L LVM-$VERSION $DEVRAM $INITRDSIZE"
335*86d7f5d3SJohn Marino[ "$VERBOSE" ] && OPT_Q="" || OPT_Q="-q"
336*86d7f5d3SJohn Marinomke2fs $OPT_Q -F -m0 -L LVM-$VERSION $DEVRAM $INITRDSIZE
337*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
338*86d7f5d3SJohn Marino   echo "$cmd -- ERROR making ram disk filesystem"
339*86d7f5d3SJohn Marino   echo "$cmd -- ERROR you need to use mke2fs >= 1.14 or increase INITRDSIZE"
340*86d7f5d3SJohn Marino   cleanup 1
341*86d7f5d3SJohn Marinofi
342*86d7f5d3SJohn Marino
343*86d7f5d3SJohn Marinoverbose "creating mountpoint $TMPMNT"
344*86d7f5d3SJohn Marinomkdir $TMPMNT
345*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
346*86d7f5d3SJohn Marino   echo "$cmd -- ERROR making $TMPMNT"
347*86d7f5d3SJohn Marino   cleanup 1
348*86d7f5d3SJohn Marinofi
349*86d7f5d3SJohn Marino
350*86d7f5d3SJohn Marinoecho "$cmd -- mounting ram disk filesystem"
351*86d7f5d3SJohn Marinoverbose "mount -o loop $DEVRAM $TMPMNT"
352*86d7f5d3SJohn Marinomount -oloop $DEVRAM $TMPMNT
353*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
354*86d7f5d3SJohn Marino   echo "$cmd -- ERROR mounting $DEVRAM on $TMPMNT"
355*86d7f5d3SJohn Marino   cleanup 1
356*86d7f5d3SJohn Marinofi
357*86d7f5d3SJohn Marino
358*86d7f5d3SJohn Marinoverbose "creating basic set of directories in $TMPMNT"
359*86d7f5d3SJohn Marino(cd $TMPMNT; mkdir bin dev etc lib proc sbin var)
360*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
361*86d7f5d3SJohn Marino   echo "$cmd -- ERROR creating directories in $TMPMNT"
362*86d7f5d3SJohn Marino   cleanup 1
363*86d7f5d3SJohn Marinofi
364*86d7f5d3SJohn Marino
365*86d7f5d3SJohn Marino# Add some /dev files. We have to handle different types of MAKEDEV invocations
366*86d7f5d3SJohn Marino# here, so this is rather messy.
367*86d7f5d3SJohn MarinoRETCODE=0
368*86d7f5d3SJohn Marinoecho "$cmd -- adding required /dev files"
369*86d7f5d3SJohn Marinoverbose "BASICDEVICES: `echo $BASICDEVICES`"
370*86d7f5d3SJohn Marinoverbose "BLOCKDEVICES: `echo $BLOCKDEVICES`"
371*86d7f5d3SJohn Marino[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q=""
372*86d7f5d3SJohn Marinocase "$MAKEDEV" in
373*86d7f5d3SJohn Marinodebian)
374*86d7f5d3SJohn Marino    (cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
375*86d7f5d3SJohn Marino    RETCODE=$?
376*86d7f5d3SJohn Marino    ;;
377*86d7f5d3SJohn Marinoredhat)
378*86d7f5d3SJohn Marino    (cd $TMPMNT/dev; /dev/MAKEDEV $OPT_Q -d $TMPMNT/dev -m 2)
379*86d7f5d3SJohn Marino    RETCODE=$?
380*86d7f5d3SJohn Marino    ;;
381*86d7f5d3SJohn Marinogentoo)
382*86d7f5d3SJohn Marino    (cd $TMPMNT/dev; /usr/sbin/MAKEDEV $OPT_Q $BASICDEVICES $BLOCKDEVICES)
383*86d7f5d3SJohn Marino    RETCODE=$?
384*86d7f5d3SJohn Marino    ;;
385*86d7f5d3SJohn Marino*)
386*86d7f5d3SJohn Marino    echo "$cmd -- ERROR: $MAKEDEV is not a known MAKEDEV style."
387*86d7f5d3SJohn Marino    RETCODE=1
388*86d7f5d3SJohn Marino    ;;
389*86d7f5d3SJohn Marinoesac
390*86d7f5d3SJohn Marino
391*86d7f5d3SJohn Marino
392*86d7f5d3SJohn Marinoif [ $RETCODE -ne 0 ]; then
393*86d7f5d3SJohn Marino   echo "$cmd -- ERROR adding /dev files"
394*86d7f5d3SJohn Marino   cleanup 1
395*86d7f5d3SJohn Marinofi
396*86d7f5d3SJohn Marino
397*86d7f5d3SJohn Marino
398*86d7f5d3SJohn Marino# copy necessary files to ram disk
399*86d7f5d3SJohn Marinoecho "$cmd -- copying initrd files to ram disk"
400*86d7f5d3SJohn Marino[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q="--quiet"
401*86d7f5d3SJohn Marinoverbose "find \$INITRDFILES | cpio -pdmL $OPT_Q $TMPMNT"
402*86d7f5d3SJohn Marinofind $INITRDFILES | cpio -pdmL $OPT_Q $TMPMNT
403*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
404*86d7f5d3SJohn Marino   echo "$cmd -- ERROR cpio to ram disk"
405*86d7f5d3SJohn Marino   cleanup 1
406*86d7f5d3SJohn Marinofi
407*86d7f5d3SJohn Marino
408*86d7f5d3SJohn Marino
409*86d7f5d3SJohn Marinoecho "$cmd -- creating symlinks to busybox"
410*86d7f5d3SJohn Marinoshopt -s extglob
411*86d7f5d3SJohn Marino[ "$VERBOSE" ] && OPT_Q="-v" || OPT_Q=""
412*86d7f5d3SJohn MarinoBUSYBOXSYMLINKS=`busybox 2>&1| awk '/^Currently defined functions:$/ {i++;next} i'|tr ',\t\n' ' '`
413*86d7f5d3SJohn Marinofor link in ${BUSYBOXSYMLINKS//@(linuxrc|init|busybox)}; do
414*86d7f5d3SJohn Marino	ln -s $OPT_Q busybox $TMPMNT/bin/$link;
415*86d7f5d3SJohn Marinodone
416*86d7f5d3SJohn Marinoshopt -u extglob
417*86d7f5d3SJohn Marino
418*86d7f5d3SJohn Marinoecho "$cmd -- creating new $TMPMNT/sbin/init"
419*86d7f5d3SJohn Marinocreate_init
420*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
421*86d7f5d3SJohn Marino   echo "$cmd -- ERROR creating init"
422*86d7f5d3SJohn Marino   cleanup
423*86d7f5d3SJohn Marino   exit 1
424*86d7f5d3SJohn Marinofi
425*86d7f5d3SJohn Marino
426*86d7f5d3SJohn Marino# copy LVMCONF into place or create a stripped down one from lvm dumpconfig
427*86d7f5d3SJohn Marinomkdir -p $TMPMNT/etc/lvm
428*86d7f5d3SJohn Marinoif [ -n "$LVMCONF" ]; then
429*86d7f5d3SJohn Marino    echo "$cmd -- copying $LVMCONF to $TMPMNT/etc/lvm/lvm.conf"
430*86d7f5d3SJohn Marino    if [ -f "$LVMCONF" ]; then
431*86d7f5d3SJohn Marino        cp $LVMCONF $TMPMNT/etc/lvm/lvm.conf
432*86d7f5d3SJohn Marino    else
433*86d7f5d3SJohn Marino        echo "$cmd -- ERROR: $LVMCONF does not exist!"
434*86d7f5d3SJohn Marino	cleanup
435*86d7f5d3SJohn Marino	exit 1
436*86d7f5d3SJohn Marino    fi
437*86d7f5d3SJohn Marinoelse
438*86d7f5d3SJohn Marino    echo "$cmd -- creating new $TMPMNT/etc/lvm/lvm.conf"
439*86d7f5d3SJohn Marino    create_lvmconf
440*86d7f5d3SJohn Marinofi
441*86d7f5d3SJohn Marino
442*86d7f5d3SJohn Marinoif [ -n "$RAID" ]; then
443*86d7f5d3SJohn Marino    RAIDLIST="$TMPMNT/etc/raid_autostart"
444*86d7f5d3SJohn Marino    echo "$cmd -- creating $RAIDLIST file."
445*86d7f5d3SJohn Marino    for device in $RAID; do
446*86d7f5d3SJohn Marino        echo $device >> $RAIDLIST
447*86d7f5d3SJohn Marino    done
448*86d7f5d3SJohn Marinofi
449*86d7f5d3SJohn Marino
450*86d7f5d3SJohn Marino# create modules.dep and /etc/modules files if needed
451*86d7f5d3SJohn Marinoif [ -n "$MODULES" ]; then
452*86d7f5d3SJohn Marino    echo "$cmd -- creating $MODDIR/modules.dep file and $TMPMNT/etc/modules"
453*86d7f5d3SJohn Marino    depmod -b $TMPMNT $VERSION
454*86d7f5d3SJohn Marino    for module in $MODULES; do
455*86d7f5d3SJohn Marino        basename $module | sed 's/\.k\{0,1\}o$//' >> $TMPMNT/etc/modules
456*86d7f5d3SJohn Marino    done
457*86d7f5d3SJohn Marinofi
458*86d7f5d3SJohn Marino
459*86d7f5d3SJohn Marinoverbose "removing $TMPMNT/lost+found"
460*86d7f5d3SJohn Marinormdir $TMPMNT/lost+found
461*86d7f5d3SJohn Marino
462*86d7f5d3SJohn Marinoecho "$cmd -- ummounting ram disk"
463*86d7f5d3SJohn Marinoumount $DEVRAM
464*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
465*86d7f5d3SJohn Marino   echo "$cmd -- ERROR umounting $DEVRAM"
466*86d7f5d3SJohn Marino   cleanup 1
467*86d7f5d3SJohn Marinofi
468*86d7f5d3SJohn Marino
469*86d7f5d3SJohn Marinoecho "$cmd -- creating compressed initrd $INITRD"
470*86d7f5d3SJohn Marinoverbose "dd if=$DEVRAM bs=1k count=$INITRDSIZE | gzip -9"
471*86d7f5d3SJohn Marinodd if=$DEVRAM bs=1k count=$INITRDSIZE 2>/dev/null | gzip -9 > $INITRD
472*86d7f5d3SJohn Marinoif [ $? -ne 0 ]; then
473*86d7f5d3SJohn Marino   echo "$cmd -- ERROR creating $INITRD"
474*86d7f5d3SJohn Marino   cleanup 1
475*86d7f5d3SJohn Marinofi
476*86d7f5d3SJohn Marino
477*86d7f5d3SJohn Marino
478*86d7f5d3SJohn Marinocat << FINALTXT
479*86d7f5d3SJohn Marino--------------------------------------------------------
480*86d7f5d3SJohn MarinoYour initrd is ready in $INITRD
481*86d7f5d3SJohn Marino
482*86d7f5d3SJohn MarinoDon't forget to set root=/dev/ram0 in kernel parameters
483*86d7f5d3SJohn MarinoDon't forget to set lvm2root=/dev/VG/LV in kernel parameters, where LV is your root volume
484*86d7f5d3SJohn MarinoIf you use lilo try adding/modifying an entry similar to this one in lilo.conf:
485*86d7f5d3SJohn Marino
486*86d7f5d3SJohn Marinoimage=/boot/vmlinuz-lvm2-$VERSION
487*86d7f5d3SJohn Marino        label="ramdisk_LVM"
488*86d7f5d3SJohn Marino        initrd=/boot/initrd-lvm2-$VERSION.gz
489*86d7f5d3SJohn Marino        append="root=/dev/ram0 lvm2root=/dev/system/root <other parameters>"
490*86d7f5d3SJohn Marino
491*86d7f5d3SJohn MarinoIf using grub try adding/modifying an entry similar to this one in menu.lst
492*86d7f5d3SJohn Marino
493*86d7f5d3SJohn Marinotitle ramdisk LVM
494*86d7f5d3SJohn Marino        kernel /boot/vmlinuz-lvm2-$VERSION root=/dev/ram0 lvm2root=/dev/system/root <other parameters>
495*86d7f5d3SJohn Marino        initrd /boot/initrd-lvm2-$VERSION.gz
496*86d7f5d3SJohn Marino
497*86d7f5d3SJohn MarinoYou can also pass lvm2rescue to the kernel to get a shell
498*86d7f5d3SJohn Marino--------------------------------------------------------
499*86d7f5d3SJohn MarinoFINALTXT
500*86d7f5d3SJohn Marino
501*86d7f5d3SJohn Marinocleanup 0
502*86d7f5d3SJohn Marino
503