From a605ac10973b145e1121c858d3955bd4ef7103b1 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Wed, 20 Apr 2016 15:37:48 -0400 Subject: btrfs-based encrypted persistent root This replaces the old LVM code with btrfs-based code. --- old-school/lvm-create.sh | 209 ++++------------------------------------------- 1 file changed, 15 insertions(+), 194 deletions(-) (limited to 'old-school') diff --git a/old-school/lvm-create.sh b/old-school/lvm-create.sh index 22016f5..ba79e0c 100644 --- a/old-school/lvm-create.sh +++ b/old-school/lvm-create.sh @@ -4,12 +4,6 @@ losetup() { /sbin/losetup "$@"; } -lvm() -{ - # get rid of warnings from lvm because we are holding open these fds - command lvm "$@" 3>&- 4>&- -} - luks_secret() { local parms=$-; # this junk keeps set -x from being too annoying @@ -33,11 +27,6 @@ mount_squashfs_images() bootdone squashfs-root } -lv_exists() -{ - [ -n "$1" ] && lvm lvs "$1" >/dev/null 2>&1 -} - floor4() { # Negatives round up, but aren't used. @@ -51,30 +40,6 @@ ceil4() printf '%d\n' "$x" } -vgfree_megs() -{ - local vg="$1" out - out=$(lvm vgs -o pv_free --noheadings --nosuffix --units m "$vg") || return - echo ${out%.*} -} - -init_samizdat_lvs() -{ - local megs_free cdrom_dev cdrom_sectors cdrom_megs root_megs - megs_free=$(vgfree_megs samizdat) || return - cdrom_dev="$(mountpoint_to_dev /cdrom)" || return - cdrom_sectors=$(blockdev --getsz "$cdrom_dev") || return - cdrom_megs=$(ceil4 $(( cdrom_sectors / 2048 ))) - root_megs=$(floor4 $(( megs_free - cdrom_megs ))) - - if [ $root_megs -le 0 ]; then # No room for cdrom mirror. Oh well, charge forward. - root_megs=$megs_free - fi - - lvm lvcreate -Z n -L ${root_megs}m -n root samizdat || return - $ROOT_MKFS_CMD /dev/mapper/samizdat-root || return -} - mount_aufs_branches() { local new="$1" @@ -95,20 +60,24 @@ init_samizdat() { local imgfile="$1" megs="$2" keyfile="$3" dev - init_samizdat_vg "$imgfile" "$megs" "$keyfile" || return - init_samizdat_lvs || return + init_samizdat_blockdev "$imgfile" "$megs" "$keyfile" || return + local blockdev=/dev/mapper/samizdatcrypt - mount_aufs_branches new + mount -t btrfs -o subvol=ROOT /cdrom/live/filesystem.btrfs /root || return + btrfs device add "$blockdev" /root || return + mount -o rw,remount /root || return + bootdone root-mounted } open_samizdat() { - open_samizdat_vg "$@" || return - - lvs=$(lvm lvs --separator / samizdat -o vg_name,lv_name --noheadings) || return - lvm lvchange -ay $lvs || return - - mount_aufs_branches + open_samizdat_blockdev "$@" || return + local blockdev=/dev/mapper/samizdatcrypt + losetup -f /cdrom/live/filesystem.btrfs || return + modprobe btrfs || return + btrfs device scan || return + mount -t btrfs -o subvol=ROOT "$blockdev" /root || return + bootdone root-mounted } init_samizdat_lodev() @@ -119,7 +88,7 @@ init_samizdat_lodev() echo "$dev" } -open_samizdat_vg() +open_samizdat_blockdev() { local imgfile="$1" keyfile="$2" dev local cryptname=samizdatcrypt @@ -134,7 +103,7 @@ open_samizdat_vg() } -init_samizdat_vg() +init_samizdat_blockdev() { local imgfile="$1" megs="$2" keyfile="$3" dev local cryptname=samizdatcrypt @@ -151,21 +120,6 @@ init_samizdat_vg() luks_secret | cryptsetup --key-file - luksOpen "$dev" "$cryptname" || return [ -b /dev/mapper/"$cryptname" ] || return - - lvm pvcreate /dev/mapper/"$cryptname" || return - lvm vgcreate samizdat /dev/mapper/"$cryptname" -} - -grow_samizdat_vg_free() -{ - # Grow the samizdat VG sufficiently to ensure it has at least $want_free_megs free. - - local want_free_megs=$(ceil4 "$1") free_megs - free_megs=$(vgfree_megs samizdat) || return - - if [ "$free_megs" -lt "$want_free_megs" ]; then - grow_samizdat_vg $((want_free_megs - free_megs)) || return - fi } majmin() @@ -176,22 +130,6 @@ majmin() printf '%d:%d\n' 0x$major 0x$minor } -vg_to_pv() -{ - lvm vgs "$1" -o devices --noheadings | - ( - found= multidev= - while read dev; do - dev=${dev%(*} - if [ "$found" -a "$found" != "$dev" ]; then - exit 1 - fi - found=$dev - done - readlink -f "$found" - ) -} - cryptdev_to_dev() { local dev="$1" majmin @@ -212,29 +150,6 @@ cryptdev_to_backing_file() printf '%s\n' "$result" } -samizdat_backing_file() -{ - local pv - pv=$(vg_to_pv samizdat) && [ "$pv" ] || return - cryptdev_to_backing_file "$pv" -} - -grow_samizdat_lv() -{ - # Increase the size of the specified LV by $megs MB, creating the LV and resizing the VG as necessary. - - local lv_name="$1" megs="$2" stat imgfile freemegs - imgfile=$(samizdat_backing_file) || return - - if lv_exists samizdat/"$lv_name"; then - grow_samizdat_vg_free "$megs" || return - lvm lvresize -r -L +${megs}m samizdat/"$lv_name" || return - else - grow_samizdat_vg_free "$megs" || return - lvm lvcreate -Z n -L ${megs}m -n "$lv_name" samizdat || return - fi -} - lodev_to_file() { local result majmin dev="$1" @@ -243,41 +158,6 @@ lodev_to_file() printf '%s' "$result" } -grow_samizdat_vg() -{ - # Increase the size of the samizdat VG by $megs MB, resizing the backing file as necessary. - - local megs="$1" cryptdev dev imgfile stat - cryptdev=$(vg_to_pv samizdat) - dev=$(cryptdev_to_dev "$cryptdev") || return - [ -b "$dev" ] || return - - if [ "$(stat -c '%t' "$dev")" = 7 ]; then # this is a loop device - - imgfile=$(lodev_to_file "$dev") || return - stat="$(stat -c 'local du=$((%B*%b)) sz=%s' "$imgfile")" || return - eval "$stat" - stat=$(stat -f -c 'local df=$((%f*%S))' "$imgfile") || return - eval "$stat" - - local min_free_space=30 - if [ $(( df - megs*1024*1024 - sz + du )) -le $((min_free_space * 1024 * 1024)) ]; then - echo 'grow_samizdat_vg: Not enough disk space!' >&2 - return -1 - fi - - truncate -cs +${megs}M "$imgfile" || return - losetup -c "$dev" || return - cryptsetup resize "$cryptdev" || return - lvm pvresize "$cryptdev" || return - - else - echo 'grow_samizdat_vg: Unimplemented!' >&2 - return 1 - - fi -} - mountpoint_to_dev() { local wantmp="$1" dev mp rest @@ -298,65 +178,6 @@ get_cdrom_sizelimit() fi } -mirror_cdrom() -{ - local md_num=55 dev mp rest cdrom_dev sectors - cdrom_dev="$(mountpoint_to_dev /cdrom)" || return - - local lv_name=samizdat/cdrom - local lv_dev=/dev/mapper/samizdat-cdrom - local md_name=/dev/md$md_num - - if [ -b $md_name ]; then - echo "RAID device already exists: '$md_name'; try removing (mdadm -S $md_name) and retry" >&2 - return 1 - fi - - if lv_exists $lv_name.tmp; then - lvm lvchange --available n $lv_name.tmp && lvm lvremove $lv_name.tmp || return - fi - - if lv_exists $lv_name; then - umount /cdrom || return - mount -r "$lv_dev" /cdrom - return - fi - - umount /cdrom || return - - sectors=$(blockdev --getsz "$cdrom_dev") || return - grow_samizdat_lv ${lv_name#samizdat/}.tmp $((sectors / 2 / 1024 + 1)) || return - - # In order to trick mdadm into accepting a read-only device, we need - # to create a (read-write) loopback device. - - # Furthermore, in order to deal with block device errors caused by - # TAO "run-out blocks" we may need to discard the last two 2048-byte - # sectors. - - local cdrom_loopdev sizelimit - cdrom_loopdev=$(losetup -f) || return - sizelimit=$(get_cdrom_sizelimit "$cdrom_dev") - - # Apparently loopdev sizelimit is not respected by linux md. Nor - # blockdev --getsz. Does it even work? Anyway, although this is used - # here redundantly, 'mdadm --size' is used as well. - /sbin/losetup ${sizelimit:+--sizelimit=$sizelimit} "$cdrom_loopdev" "$cdrom_dev" || return - - mdadm --build $md_name ${sizelimit:+--size=$((sizelimit / 1024))} \ - --level=1 --raid-devices=1 --force --write-mostly "$cdrom_loopdev" || return - mdadm -D $md_name >&2 - mdadm --add $md_name $lv_dev.tmp - mdadm -D $md_name >&2 - mdadm --grow $md_name -n 2 - mdadm -D $md_name >&2 - - mount -r $md_name /cdrom || { mount -r "$cdrom_dev" /cdrom; return 1; } - - chpst -P samizdat-cdrom-copy "$md_name" "$lv_name" "$lv_dev" "$cdrom_loopdev" "$cdrom_dev" & - echo "[$$] Launched RAID monitor with pid $!." >&2 -} - init_gpg() { bootwait samizdat-cdrom -- cgit v1.2.3