I've reworked the initrd this afternoon to support this. It's something I've been meaning to do for a while as I also had a system with 2 encrypted lvm volumes. You'll have to enter the password for each encrypted device, but at least it means you can use more than 1.
Anyway, here's my patch if anyone is interested:
Code:
--- mkinitrd/init 2009-04-02 23:13:59.000000000 +0100
+++ mkinitrd.new/init 2010-02-03 15:48:40.057727815 +0000
@@ -136,33 +136,33 @@
/sbin/mdadm -E -s >/etc/mdadm.conf
/sbin/mdadm -A -s
fi
-
- # Find root device if a label was given:
- if echo $ROOTDEV | grep -q "LABEL=" ; then
- ROOTDEV=`findfs $ROOTDEV`
- fi
- # Make encrypted root partition available:
- # The useable device will be under /dev/mapper/
- # Three scenarios for the commandline exist:
- # 1- ROOTDEV is on a LUKS volume, and LUKSDEV is a real block device
- # 2- ROOTDEV is on a LVM volume, and LUKSDEV is a real block device
- # 3- ROOTDEV is on a LUKS volume, and LUKSDEV is on a LVM volume
- # Case (3) will have to wait until we initialize the LVM.
- # Test if ROOTDEV is "/dev/someting" or just "something" - the first means
- # ROOTDEV is on a LVM volume (scenario 2); we don't need to rewrite ROOTDEV.
- # The second means that ROOTDEV is on a LUKS volume (scenario 1).
- CRYPTDEV=""
+ # Unlock any encrypted partitions necessary to access the
+ # root filesystem, such as encrypted LVM Physical volumes, disk
+ # partitions or mdadm arrays.
+ # Unavailable devices such as LVM Logical Volumes will need to be
+ # deferred until they become available after the vgscan.
+
if [ -x /sbin/cryptsetup ]; then
- # If we find a LUKS device now, it is on a real block device:
- if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
- CRYPTDEV=$(basename $ROOTDEV)
- echo "Unlocking LUKS crypt volume '${CRYPTDEV}' on device '$LUKSDEV':"
- /sbin/cryptsetup luksOpen ${LUKSDEV} $CRYPTDEV </dev/systty >/dev/systty 2>&1
- if [ "$CRYPTDEV" == "$ROOTDEV" ]; then # scenario 1
- ROOTDEV="/dev/mapper/${CRYPTDEV}"
- fi
- fi
+ sleep 2 # Brief pause to Prevent usb keyboard activation from
+ # obscuring the cryptsetup prompt on the console.
+ LUKSLIST_DEFERRED=''
+ LUKSLIST=`echo $LUKSDEV | tr ':' ' '`
+ for LUKSDEV in $LUKSLIST
+ do
+ if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
+ CRYPTDEV=luks$(basename $LUKSDEV)
+ echo "Unlocking LUKS encrypted device '${LUKSDEV}'" \
+ "as luks mapped device '$CRYPTDEV':"
+ /sbin/cryptsetup luksOpen ${LUKSDEV} $CRYPTDEV \
+ </dev/systty >/dev/systty 2>&1
+ if [ "$ROOTDEV" = "$LUKSDEV" ] ; then
+ ROOTDEV="/dev/mapper/$CRYPTDEV"
+ fi
+ else
+ LUKSLIST_DEFERRED="${LUKSLIST_DEFERRED} ${LUKSDEV}"
+ fi
+ done
fi
# Initialize LVM:
@@ -172,17 +172,31 @@
/sbin/vgchange -ay --ignorelockingfailure
fi
- # Make encrypted root partition available (scenario 3):
- # We have to handle cases here where the LUKS volume is created on a LV
- if [ -x /sbin/cryptsetup ]; then
- if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
- # Only act if we could not open the LUKS device before (i.e. is on a LV):
- if [ "x$CRYPTDEV" == "x" ]; then
- echo "Unlocking LUKS crypt volume '${ROOTDEV}' on device '$LUKSDEV':"
- /sbin/cryptsetup luksOpen ${LUKSDEV} $ROOTDEV </dev/systty >/dev/systty 2>&1
- ROOTDEV="/dev/mapper/${ROOTDEV}"
- fi
- fi
+ # Unlock any LUKS encrypted devices that were deferred above which
+ # have now become available due to the vgscan.
+ # i.e. Filesystems on LVM Logical Volumes.
+
+ if [ -x /sbin/cryptsetup -a -n "${LUKSLIST_DEFERRED}"]; then
+ for LUKSDEV in ${LUKSLIST_DEFERRED}
+ do
+ if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
+ CRYPTDEV=luks$(basename $LUKSDEV)
+ echo "Unlocking LUKS encrypted device '${LUKSDEV}'" \
+ "as luks mapped device '$CRYPTDEV':"
+ /sbin/cryptsetup luksOpen ${LUKSDEV} $CRYPTDEV \
+ </dev/systty >/dev/systty 2>&1
+ if [ "$ROOTDEV" = "$LUKSDEV" ] ; then
+ ROOTDEV="/dev/mapper/$CRYPTDEV"
+ fi
+ else
+ echo "LUKS device $LUKSDEV unavailable for unlocking"
+ fi
+ done
+ fi
+
+ # Find root device if a label was given:
+ if echo $ROOTDEV | grep -q "LABEL=" ; then
+ ROOTDEV=`findfs $ROOTDEV`
fi
# Resume state from swap
It's a complete reorganisation of the bits surrounding luks and lvm in the initrd-tree/init. IMO it's actually simpler than the existing code and has the advantage of adding the new feature.
The way it works is that it'll allow you to use a list, similar to how you specify modules with the -m option e.g. "-C /dev/sda1:/dev/sda2:/dev/sda3" on your mkinitrd or on the luksdev= kernel option for all the disks you want to be unlocked during the initrd.
Each luks device will automatically be given the name /dev/mapper/luksnnnn where nnnn is the underlying basename of the device so the above would result in lukssda1, lukssda2, lukssda3 which results in a consistent naming and a clear correlation of what device it actually relates to.
As before -r option is used to specify the rootfs, but has also been reworked a little. It works in a more consistent manner than the way it works currently. You no longer use the short luks name for a luks setup and a the full device path for a lvm logical volume, Instead you simply use whatever your root fs is on whether its an encrypted partition or logical volume.
e.g.
If your rootfs was on an encrypted /dev/sda1, in the current version you'd have to use "-C /dev/sda1 -r cryptroot"
With mine you'd use "-C /dev/sda1 -r /dev/sda1" (the init will work out that it needs to use /dev/mapper/lukssda1 itself, though you could explicitly specify "-r /dev/mapper/lukssda1" yourself if you prefer.
If you have an encrypted root on sda1 and an encrypted home on sda2 you can use "-C /dev/sda1:/dev/sda2 -r /dev/sda1" though in this case you'd probably be best off just using crypttab. Still, it'll work.
For a LVM setup where your physical volumes are encrypted, such as described in the CRYPT and LVM READMEs on the install disk, you'd use
"-C /dev/sda1 -r /dev/vgname/lvname"
What's new is that you can now have more than one pv and do something like "-C /dev/sda1:/dev/sda2:/dev/sda3 -r /dev/vgname/lvname"
For root fs on an encrypted LVM logical volume on a non-encrypted lvm physical volume you use "-C /dev/vgname/lvname -r /dev/vgname/lvname"
I couldn't get the mkinitrd.SlackBuild from Slackware64-current to work, it bombs out building busybox, so to install the patch to a running system you have to go through a little bit of a hack. (remember that if you update the slackware mkinitrd package you'll lose this).
Code:
oot@nix:/root# cd /tmp
root@nix:/tmp# mkdir initrd-tree
root@nix:/tmp# cd initrd-tree
root@nix:/tmp/initrd-tree# tar -zxf /usr/share/mkinitrd/initrd-tree.tar.gz
root@nix:/tmp/initrd-tree# patch -p1 <mkinitrd.diff
patching file init
root@nix:/tmp/initrd-tree# mv /usr/share/mkinitrd/initrd-tree.tar.gz /usr/share/mkinitrd/initrd-tree.tar.gz.orig
root@nix:/tmp/initrd-tree# tar -zcf /usr/share/mkinitrd/initrd-tree.tar.gz .
To implement this properly then the /sbin/mkinitrd really should be made to match, but it does work as it is (at least on my config).
I'd be interested in any feedback, especially from eric on this, especially so if I've missed a 'nasty' in here anywhere.
If anyone thinks they'd like to test it then I'll be happy to answer questions, but be aware that it's only been tested on my box, so it's not had exposure to many different configs yet.
Use at your own risk!!!.