summaryrefslogtreecommitdiff
path: root/old-school/lvm-create.sh
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2016-04-20 15:37:48 -0400
committerAndrew Cady <d@jerkface.net>2016-04-20 15:37:52 -0400
commita605ac10973b145e1121c858d3955bd4ef7103b1 (patch)
treeb743e2e40cfd07cea820128c429fc0f38140d8b6 /old-school/lvm-create.sh
parent1bddec3db035c4878a91fba7ce585b4ac727a89f (diff)
btrfs-based encrypted persistent root
This replaces the old LVM code with btrfs-based code.
Diffstat (limited to 'old-school/lvm-create.sh')
-rw-r--r--old-school/lvm-create.sh209
1 files changed, 15 insertions, 194 deletions
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 @@
4 4
5losetup() { /sbin/losetup "$@"; } 5losetup() { /sbin/losetup "$@"; }
6 6
7lvm()
8{
9 # get rid of warnings from lvm because we are holding open these fds
10 command lvm "$@" 3>&- 4>&-
11}
12
13luks_secret() 7luks_secret()
14{ 8{
15 local parms=$-; # this junk keeps set -x from being too annoying 9 local parms=$-; # this junk keeps set -x from being too annoying
@@ -33,11 +27,6 @@ mount_squashfs_images()
33 bootdone squashfs-root 27 bootdone squashfs-root
34} 28}
35 29
36lv_exists()
37{
38 [ -n "$1" ] && lvm lvs "$1" >/dev/null 2>&1
39}
40
41floor4() 30floor4()
42{ 31{
43 # Negatives round up, but aren't used. 32 # Negatives round up, but aren't used.
@@ -51,30 +40,6 @@ ceil4()
51 printf '%d\n' "$x" 40 printf '%d\n' "$x"
52} 41}
53 42
54vgfree_megs()
55{
56 local vg="$1" out
57 out=$(lvm vgs -o pv_free --noheadings --nosuffix --units m "$vg") || return
58 echo ${out%.*}
59}
60
61init_samizdat_lvs()
62{
63 local megs_free cdrom_dev cdrom_sectors cdrom_megs root_megs
64 megs_free=$(vgfree_megs samizdat) || return
65 cdrom_dev="$(mountpoint_to_dev /cdrom)" || return
66 cdrom_sectors=$(blockdev --getsz "$cdrom_dev") || return
67 cdrom_megs=$(ceil4 $(( cdrom_sectors / 2048 )))
68 root_megs=$(floor4 $(( megs_free - cdrom_megs )))
69
70 if [ $root_megs -le 0 ]; then # No room for cdrom mirror. Oh well, charge forward.
71 root_megs=$megs_free
72 fi
73
74 lvm lvcreate -Z n -L ${root_megs}m -n root samizdat || return
75 $ROOT_MKFS_CMD /dev/mapper/samizdat-root || return
76}
77
78mount_aufs_branches() 43mount_aufs_branches()
79{ 44{
80 local new="$1" 45 local new="$1"
@@ -95,20 +60,24 @@ init_samizdat()
95{ 60{
96 local imgfile="$1" megs="$2" keyfile="$3" dev 61 local imgfile="$1" megs="$2" keyfile="$3" dev
97 62
98 init_samizdat_vg "$imgfile" "$megs" "$keyfile" || return 63 init_samizdat_blockdev "$imgfile" "$megs" "$keyfile" || return
99 init_samizdat_lvs || return 64 local blockdev=/dev/mapper/samizdatcrypt
100 65
101 mount_aufs_branches new 66 mount -t btrfs -o subvol=ROOT /cdrom/live/filesystem.btrfs /root || return
67 btrfs device add "$blockdev" /root || return
68 mount -o rw,remount /root || return
69 bootdone root-mounted
102} 70}
103 71
104open_samizdat() 72open_samizdat()
105{ 73{
106 open_samizdat_vg "$@" || return 74 open_samizdat_blockdev "$@" || return
107 75 local blockdev=/dev/mapper/samizdatcrypt
108 lvs=$(lvm lvs --separator / samizdat -o vg_name,lv_name --noheadings) || return 76 losetup -f /cdrom/live/filesystem.btrfs || return
109 lvm lvchange -ay $lvs || return 77 modprobe btrfs || return
110 78 btrfs device scan || return
111 mount_aufs_branches 79 mount -t btrfs -o subvol=ROOT "$blockdev" /root || return
80 bootdone root-mounted
112} 81}
113 82
114init_samizdat_lodev() 83init_samizdat_lodev()
@@ -119,7 +88,7 @@ init_samizdat_lodev()
119 echo "$dev" 88 echo "$dev"
120} 89}
121 90
122open_samizdat_vg() 91open_samizdat_blockdev()
123{ 92{
124 local imgfile="$1" keyfile="$2" dev 93 local imgfile="$1" keyfile="$2" dev
125 local cryptname=samizdatcrypt 94 local cryptname=samizdatcrypt
@@ -134,7 +103,7 @@ open_samizdat_vg()
134 103
135} 104}
136 105
137init_samizdat_vg() 106init_samizdat_blockdev()
138{ 107{
139 local imgfile="$1" megs="$2" keyfile="$3" dev 108 local imgfile="$1" megs="$2" keyfile="$3" dev
140 local cryptname=samizdatcrypt 109 local cryptname=samizdatcrypt
@@ -151,21 +120,6 @@ init_samizdat_vg()
151 luks_secret | cryptsetup --key-file - luksOpen "$dev" "$cryptname" || return 120 luks_secret | cryptsetup --key-file - luksOpen "$dev" "$cryptname" || return
152 121
153 [ -b /dev/mapper/"$cryptname" ] || return 122 [ -b /dev/mapper/"$cryptname" ] || return
154
155 lvm pvcreate /dev/mapper/"$cryptname" || return
156 lvm vgcreate samizdat /dev/mapper/"$cryptname"
157}
158
159grow_samizdat_vg_free()
160{
161 # Grow the samizdat VG sufficiently to ensure it has at least $want_free_megs free.
162
163 local want_free_megs=$(ceil4 "$1") free_megs
164 free_megs=$(vgfree_megs samizdat) || return
165
166 if [ "$free_megs" -lt "$want_free_megs" ]; then
167 grow_samizdat_vg $((want_free_megs - free_megs)) || return
168 fi
169} 123}
170 124
171majmin() 125majmin()
@@ -176,22 +130,6 @@ majmin()
176 printf '%d:%d\n' 0x$major 0x$minor 130 printf '%d:%d\n' 0x$major 0x$minor
177} 131}
178 132
179vg_to_pv()
180{
181 lvm vgs "$1" -o devices --noheadings |
182 (
183 found= multidev=
184 while read dev; do
185 dev=${dev%(*}
186 if [ "$found" -a "$found" != "$dev" ]; then
187 exit 1
188 fi
189 found=$dev
190 done
191 readlink -f "$found"
192 )
193}
194
195cryptdev_to_dev() 133cryptdev_to_dev()
196{ 134{
197 local dev="$1" majmin 135 local dev="$1" majmin
@@ -212,29 +150,6 @@ cryptdev_to_backing_file()
212 printf '%s\n' "$result" 150 printf '%s\n' "$result"
213} 151}
214 152
215samizdat_backing_file()
216{
217 local pv
218 pv=$(vg_to_pv samizdat) && [ "$pv" ] || return
219 cryptdev_to_backing_file "$pv"
220}
221
222grow_samizdat_lv()
223{
224 # Increase the size of the specified LV by $megs MB, creating the LV and resizing the VG as necessary.
225
226 local lv_name="$1" megs="$2" stat imgfile freemegs
227 imgfile=$(samizdat_backing_file) || return
228
229 if lv_exists samizdat/"$lv_name"; then
230 grow_samizdat_vg_free "$megs" || return
231 lvm lvresize -r -L +${megs}m samizdat/"$lv_name" || return
232 else
233 grow_samizdat_vg_free "$megs" || return
234 lvm lvcreate -Z n -L ${megs}m -n "$lv_name" samizdat || return
235 fi
236}
237
238lodev_to_file() 153lodev_to_file()
239{ 154{
240 local result majmin dev="$1" 155 local result majmin dev="$1"
@@ -243,41 +158,6 @@ lodev_to_file()
243 printf '%s' "$result" 158 printf '%s' "$result"
244} 159}
245 160
246grow_samizdat_vg()
247{
248 # Increase the size of the samizdat VG by $megs MB, resizing the backing file as necessary.
249
250 local megs="$1" cryptdev dev imgfile stat
251 cryptdev=$(vg_to_pv samizdat)
252 dev=$(cryptdev_to_dev "$cryptdev") || return
253 [ -b "$dev" ] || return
254
255 if [ "$(stat -c '%t' "$dev")" = 7 ]; then # this is a loop device
256
257 imgfile=$(lodev_to_file "$dev") || return
258 stat="$(stat -c 'local du=$((%B*%b)) sz=%s' "$imgfile")" || return
259 eval "$stat"
260 stat=$(stat -f -c 'local df=$((%f*%S))' "$imgfile") || return
261 eval "$stat"
262
263 local min_free_space=30
264 if [ $(( df - megs*1024*1024 - sz + du )) -le $((min_free_space * 1024 * 1024)) ]; then
265 echo 'grow_samizdat_vg: Not enough disk space!' >&2
266 return -1
267 fi
268
269 truncate -cs +${megs}M "$imgfile" || return
270 losetup -c "$dev" || return
271 cryptsetup resize "$cryptdev" || return
272 lvm pvresize "$cryptdev" || return
273
274 else
275 echo 'grow_samizdat_vg: Unimplemented!' >&2
276 return 1
277
278 fi
279}
280
281mountpoint_to_dev() 161mountpoint_to_dev()
282{ 162{
283 local wantmp="$1" dev mp rest 163 local wantmp="$1" dev mp rest
@@ -298,65 +178,6 @@ get_cdrom_sizelimit()
298 fi 178 fi
299} 179}
300 180
301mirror_cdrom()
302{
303 local md_num=55 dev mp rest cdrom_dev sectors
304 cdrom_dev="$(mountpoint_to_dev /cdrom)" || return
305
306 local lv_name=samizdat/cdrom
307 local lv_dev=/dev/mapper/samizdat-cdrom
308 local md_name=/dev/md$md_num
309
310 if [ -b $md_name ]; then
311 echo "RAID device already exists: '$md_name'; try removing (mdadm -S $md_name) and retry" >&2
312 return 1
313 fi
314
315 if lv_exists $lv_name.tmp; then
316 lvm lvchange --available n $lv_name.tmp && lvm lvremove $lv_name.tmp || return
317 fi
318
319 if lv_exists $lv_name; then
320 umount /cdrom || return
321 mount -r "$lv_dev" /cdrom
322 return
323 fi
324
325 umount /cdrom || return
326
327 sectors=$(blockdev --getsz "$cdrom_dev") || return
328 grow_samizdat_lv ${lv_name#samizdat/}.tmp $((sectors / 2 / 1024 + 1)) || return
329
330 # In order to trick mdadm into accepting a read-only device, we need
331 # to create a (read-write) loopback device.
332
333 # Furthermore, in order to deal with block device errors caused by
334 # TAO "run-out blocks" we may need to discard the last two 2048-byte
335 # sectors.
336
337 local cdrom_loopdev sizelimit
338 cdrom_loopdev=$(losetup -f) || return
339 sizelimit=$(get_cdrom_sizelimit "$cdrom_dev")
340
341 # Apparently loopdev sizelimit is not respected by linux md. Nor
342 # blockdev --getsz. Does it even work? Anyway, although this is used
343 # here redundantly, 'mdadm --size' is used as well.
344 /sbin/losetup ${sizelimit:+--sizelimit=$sizelimit} "$cdrom_loopdev" "$cdrom_dev" || return
345
346 mdadm --build $md_name ${sizelimit:+--size=$((sizelimit / 1024))} \
347 --level=1 --raid-devices=1 --force --write-mostly "$cdrom_loopdev" || return
348 mdadm -D $md_name >&2
349 mdadm --add $md_name $lv_dev.tmp
350 mdadm -D $md_name >&2
351 mdadm --grow $md_name -n 2
352 mdadm -D $md_name >&2
353
354 mount -r $md_name /cdrom || { mount -r "$cdrom_dev" /cdrom; return 1; }
355
356 chpst -P samizdat-cdrom-copy "$md_name" "$lv_name" "$lv_dev" "$cdrom_loopdev" "$cdrom_dev" &
357 echo "[$$] Launched RAID monitor with pid $!." >&2
358}
359
360init_gpg() 181init_gpg()
361{ 182{
362 bootwait samizdat-cdrom 183 bootwait samizdat-cdrom