~ubuntu-branches/ubuntu/breezy/lvm2/breezy

« back to all changes in this revision

Viewing changes to scripts/lvm2create_initrd/lvm2create_initrd

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Caulfield
  • Date: 2004-11-03 09:37:56 UTC
  • Revision ID: james.westby@ubuntu.com-20041103093756-jt0nj8z0v8k1lyiv
Tags: upstream-2.00.25
ImportĀ upstreamĀ versionĀ 2.00.25

Show diffs side-by-side

added added

removed removed

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