diff options
author | Andrew Cady <d@jerkface.net> | 2016-04-20 15:37:48 -0400 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2016-04-20 15:37:52 -0400 |
commit | a605ac10973b145e1121c858d3955bd4ef7103b1 (patch) | |
tree | b743e2e40cfd07cea820128c429fc0f38140d8b6 /old-school/lvm-create.sh | |
parent | 1bddec3db035c4878a91fba7ce585b4ac727a89f (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.sh | 209 |
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 | ||
5 | losetup() { /sbin/losetup "$@"; } | 5 | losetup() { /sbin/losetup "$@"; } |
6 | 6 | ||
7 | lvm() | ||
8 | { | ||
9 | # get rid of warnings from lvm because we are holding open these fds | ||
10 | command lvm "$@" 3>&- 4>&- | ||
11 | } | ||
12 | |||
13 | luks_secret() | 7 | luks_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 | ||
36 | lv_exists() | ||
37 | { | ||
38 | [ -n "$1" ] && lvm lvs "$1" >/dev/null 2>&1 | ||
39 | } | ||
40 | |||
41 | floor4() | 30 | floor4() |
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 | ||
54 | vgfree_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 | |||
61 | init_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 | |||
78 | mount_aufs_branches() | 43 | mount_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 | ||
104 | open_samizdat() | 72 | open_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 | ||
114 | init_samizdat_lodev() | 83 | init_samizdat_lodev() |
@@ -119,7 +88,7 @@ init_samizdat_lodev() | |||
119 | echo "$dev" | 88 | echo "$dev" |
120 | } | 89 | } |
121 | 90 | ||
122 | open_samizdat_vg() | 91 | open_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 | ||
137 | init_samizdat_vg() | 106 | init_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 | |||
159 | grow_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 | ||
171 | majmin() | 125 | majmin() |
@@ -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 | ||
179 | vg_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 | |||
195 | cryptdev_to_dev() | 133 | cryptdev_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 | ||
215 | samizdat_backing_file() | ||
216 | { | ||
217 | local pv | ||
218 | pv=$(vg_to_pv samizdat) && [ "$pv" ] || return | ||
219 | cryptdev_to_backing_file "$pv" | ||
220 | } | ||
221 | |||
222 | grow_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 | |||
238 | lodev_to_file() | 153 | lodev_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 | ||
246 | grow_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 | |||
281 | mountpoint_to_dev() | 161 | mountpoint_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 | ||
301 | mirror_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 | |||
360 | init_gpg() | 181 | init_gpg() |
361 | { | 182 | { |
362 | bootwait samizdat-cdrom | 183 | bootwait samizdat-cdrom |