]> git.ipfire.org Git - thirdparty/dracut.git/blob - modules.d/90dmsquash-live/dmsquash-live-root.sh
ac6034081d764904929efc35399e85125b40da20
[thirdparty/dracut.git] / modules.d / 90dmsquash-live / dmsquash-live-root.sh
1 #!/bin/sh
2
3 type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
4
5 command -v unpack_archive >/dev/null || . /lib/img-lib.sh
6
7 PATH=/usr/sbin:/usr/bin:/sbin:/bin
8
9 if getargbool 0 rd.live.debug -n -y rdlivedebug; then
10 exec > /tmp/liveroot.$$.out
11 exec 2>> /tmp/liveroot.$$.out
12 set -x
13 fi
14
15 [ -z "$1" ] && exit 1
16 livedev="$1"
17
18 # parse various live image specific options that make sense to be
19 # specified as their own things
20 live_dir=$(getarg rd.live.dir -d live_dir)
21 [ -z "$live_dir" ] && live_dir="LiveOS"
22 squash_image=$(getarg rd.live.squashimg)
23 [ -z "$squash_image" ] && squash_image="squashfs.img"
24
25 getargbool 0 rd.live.ram -d -y live_ram && live_ram="yes"
26 getargbool 0 rd.live.overlay.reset -d -y reset_overlay && reset_overlay="yes"
27 getargbool 0 rd.live.overlay.readonly -d -y readonly_overlay && readonly_overlay="--readonly" || readonly_overlay=""
28 overlay=$(getarg rd.live.overlay -d overlay)
29 getargbool 0 rd.writable.fsimg -d -y writable_fsimg && writable_fsimg="yes"
30 overlay_size=$(getarg rd.live.overlay.size=)
31 [ -z "$overlay_size" ] && overlay_size=32768
32
33 getargbool 0 rd.live.overlay.thin && thin_snapshot="yes"
34 getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes"
35
36 # CD/DVD media check
37 [ -b $livedev ] && fs=$(blkid -s TYPE -o value $livedev)
38 if [ "$fs" = "iso9660" -o "$fs" = "udf" ]; then
39 check="yes"
40 fi
41 getarg rd.live.check -d check || check=""
42 if [ -n "$check" ]; then
43 type plymouth >/dev/null 2>&1 && plymouth --hide-splash
44 if [ -n "$DRACUT_SYSTEMD" ]; then
45 p=$(dev_unit_name "$livedev")
46 systemctl start checkisomd5@${p}.service
47 else
48 checkisomd5 --verbose $livedev
49 fi
50 if [ $? -eq 1 ]; then
51 die "CD check failed!"
52 exit 1
53 fi
54 type plymouth >/dev/null 2>&1 && plymouth --show-splash
55 fi
56
57 ln -s $livedev /run/initramfs/livedev
58
59 # determine filesystem type for a filesystem image
60 det_img_fs() {
61 udevadm settle >&2
62 blkid -s TYPE -u noraid -o value "$1"
63 }
64
65 modprobe squashfs
66 CMDLINE=$(getcmdline)
67 for arg in $CMDLINE; do case $arg in ro|rw) liverw=$arg ;; esac; done
68 # mount the backing of the live image first
69 mkdir -m 0755 -p /run/initramfs/live
70 if [ -f $livedev ]; then
71 # no mount needed - we've already got the LiveOS image in initramfs
72 # check filesystem type and handle accordingly
73 fstype=$(det_img_fs $livedev)
74 case $fstype in
75 squashfs) SQUASHED=$livedev;;
76 auto) die "cannot mount live image (unknown filesystem type)" ;;
77 *) FSIMG=$livedev ;;
78 esac
79 [ -e /sys/fs/$fstype ] || modprobe $fstype
80 else
81 if [ "$(blkid -o value -s TYPE $livedev)" != "ntfs" ]; then
82 mount -n -t $fstype -o ${liverw:-ro} $livedev /run/initramfs/live
83 else
84 # Symlinking /usr/bin/ntfs-3g as /sbin/mount.ntfs seems to boot
85 # at the first glance, but ends with lots and lots of squashfs
86 # errors, because systemd attempts to kill the ntfs-3g process?!
87 if [ -x "/usr/bin/ntfs-3g" ]; then
88 ( exec -a @ntfs-3g ntfs-3g -o ${liverw:-ro} $livedev /run/initramfs/live ) | vwarn
89 else
90 die "Failed to mount block device of live image: Missing NTFS support"
91 exit 1
92 fi
93 fi
94
95 if [ "$?" != "0" ]; then
96 die "Failed to mount block device of live image"
97 exit 1
98 fi
99 fi
100
101 # overlay setup helper function
102 do_live_overlay() {
103 # create a sparse file for the overlay
104 # overlay: if non-ram overlay searching is desired, do it,
105 # otherwise, create traditional overlay in ram
106
107 l=$(blkid -s LABEL -o value $livedev) || l=""
108 u=$(blkid -s UUID -o value $livedev) || u=""
109
110 if [ -z "$overlay" ]; then
111 pathspec="/${live_dir}/overlay-$l-$u"
112 elif ( echo $overlay | grep -q ":" ); then
113 # pathspec specified, extract
114 pathspec=$( echo $overlay | sed -e 's/^.*://' )
115 fi
116
117 if [ -z "$pathspec" -o "$pathspec" = "auto" ]; then
118 pathspec="/${live_dir}/overlay-$l-$u"
119 fi
120 devspec=$( echo $overlay | sed -e 's/:.*$//' )
121
122 # need to know where to look for the overlay
123 if [ -z "$setup" -a -n "$devspec" -a -n "$pathspec" -a -n "$overlay" ]; then
124 mkdir -m 0755 /run/initramfs/overlayfs
125 opt=''
126 [ -n "$readonly_overlay" ] && opt=-r
127 mount -n -t auto $devspec /run/initramfs/overlayfs || :
128 if [ -f /run/initramfs/overlayfs$pathspec -a -w /run/initramfs/overlayfs$pathspec ]; then
129 OVERLAY_LOOPDEV=$(losetup -f --show $opt /run/initramfs/overlayfs$pathspec)
130 over=$OVERLAY_LOOPDEV
131 umount -l /run/initramfs/overlayfs || :
132 oltype=$(det_img_fs $OVERLAY_LOOPDEV)
133 if [ -z "$oltype" ] || [ "$oltype" = DM_snapshot_cow ]; then
134 if [ -n "$reset_overlay" ]; then
135 info "Resetting the Device-mapper overlay."
136 dd if=/dev/zero of=$OVERLAY_LOOPDEV bs=64k count=1 conv=fsync 2>/dev/null
137 fi
138 if [ -n "$overlayfs" ]; then
139 unset -v overlayfs
140 [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="yes"
141 fi
142 setup="yes"
143 else
144 mount -n -t $oltype $opt $OVERLAY_LOOPDEV /run/initramfs/overlayfs
145 if [ -d /run/initramfs/overlayfs/overlayfs ] &&
146 [ -d /run/initramfs/overlayfs/ovlwork ]; then
147 ln -s /run/initramfs/overlayfs/overlayfs /run/overlayfs$opt
148 ln -s /run/initramfs/overlayfs/ovlwork /run/ovlwork$opt
149 if [ -z "$overlayfs" ]; then
150 overlayfs="yes"
151 [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="yes"
152 fi
153 setup="yes"
154 fi
155 fi
156 elif [ -d /run/initramfs/overlayfs$pathspec ] &&
157 [ -d /run/initramfs/overlayfs$pathspec/../ovlwork ]; then
158 ln -s /run/initramfs/overlayfs$pathspec /run/overlayfs$opt
159 ln -s /run/initramfs/overlayfs$pathspec/../ovlwork /run/ovlwork$opt
160 if [ -z "$overlayfs" ]; then
161 overlayfs="yes"
162 [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="yes"
163 fi
164 setup="yes"
165 fi
166 fi
167 if [ -n "$overlayfs" ]; then
168 modprobe overlay
169 if [ $? != 0 ]; then
170 m='OverlayFS is not available; using temporary Device-mapper overlay.'
171 unset -v overlayfs setup
172 [ -n "$reloadsysrootmountunit" ] && unset -v reloadsysrootmountunit
173 fi
174 fi
175
176 if [ -z "$setup" -o -n "$readonly_overlay" ]; then
177 if [ -n "$setup" ]; then
178 warn "Using temporary overlay."
179 elif [ -n "$devspec" -a -n "$pathspec" ]; then
180 [ -z "$m" ] &&
181 m=' Unable to find a persistent overlay; using a temporary one.'
182 m="$m"$'\n All root filesystem changes will be lost on shutdown.'
183 m="$m"$'\n Press [Enter] to continue.'
184 echo -e "\n\n\n\n${m}\n\n\n" > /dev/kmsg
185 if [ -n "$DRACUT_SYSTEMD" ]; then
186 if type plymouth >/dev/null 2>&1 && plymouth --ping ; then
187 if getargbool 0 rhgb || getargbool 0 splash ; then
188 m='>>>'$'\n''>>>'$'\n''>>>'$'\n\n\n'"$m"
189 m="${m%n.*}"$'n.\n\n\n''<<<'$'\n''<<<'$'\n''<<<'
190 plymouth display-message --text="${m}"
191 else
192 plymouth ask-question --prompt="${m}" --command=true
193 fi
194 else
195 m=">>>${m//.[[:space:]]/.} <<<"
196 systemd-ask-password --timeout=0 "${m}"
197 fi
198 else
199 type plymouth >/dev/null 2>&1 && plymouth --ping && plymouth --quit
200 read -s -r -p $'\n\n'"${m}" -n 1 reply
201 fi
202 fi
203 if [ -n "$overlayfs" ]; then
204 mkdir -m 0755 /run/overlayfs
205 mkdir -m 0755 /run/ovlwork
206 else
207 dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((overlay_size*1024)) 2> /dev/null
208 if [ -n "$setup" -a -n "$readonly_overlay" ]; then
209 RO_OVERLAY_LOOPDEV=$(losetup -f --show /overlay)
210 over=$RO_OVERLAY_LOOPDEV
211 else
212 OVERLAY_LOOPDEV=$(losetup -f --show /overlay)
213 over=$OVERLAY_LOOPDEV
214 fi
215 fi
216 fi
217
218 # set up the snapshot
219 if [ -z "$overlayfs" ]; then
220 if [ -n "$readonly_overlay" ] && [ -n "$OVERLAY_LOOPDEV" ]; then
221 echo 0 $sz snapshot $BASE_LOOPDEV $OVERLAY_LOOPDEV P 8 | dmsetup create --readonly live-ro
222 base="/dev/mapper/live-ro"
223 else
224 base=$BASE_LOOPDEV
225 fi
226 fi
227
228 if [ -n "$thin_snapshot" ]; then
229 modprobe dm_thin_pool
230 mkdir -m 0755 /run/initramfs/thin-overlay
231
232 # In block units (512b)
233 thin_data_sz=$(( $overlay_size * 1024 * 1024 / 512 ))
234 thin_meta_sz=$(( $thin_data_sz / 10 ))
235
236 # It is important to have the backing file on a tmpfs
237 # this is needed to let the loopdevice support TRIM
238 dd if=/dev/null of=/run/initramfs/thin-overlay/meta bs=1b count=1 seek=$((thin_meta_sz)) 2> /dev/null
239 dd if=/dev/null of=/run/initramfs/thin-overlay/data bs=1b count=1 seek=$((thin_data_sz)) 2> /dev/null
240
241 THIN_META_LOOPDEV=$( losetup --show -f /run/initramfs/thin-overlay/meta )
242 THIN_DATA_LOOPDEV=$( losetup --show -f /run/initramfs/thin-overlay/data )
243
244 echo 0 $thin_data_sz thin-pool $THIN_META_LOOPDEV $THIN_DATA_LOOPDEV 1024 1024 | dmsetup create live-overlay-pool
245 dmsetup message /dev/mapper/live-overlay-pool 0 "create_thin 0"
246
247 # Create a snapshot of the base image
248 echo 0 $sz thin /dev/mapper/live-overlay-pool 0 $base | dmsetup create live-rw
249 elif [ -z "$overlayfs" ]; then
250 echo 0 $sz snapshot $base $over PO 8 | dmsetup create live-rw
251 fi
252
253 # Create a device that always points to a ro base image
254 if [ -n "$overlayfs" ]; then
255 BASE_LOOPDUP=$(losetup -f --show -r $BASE_LOOPDEV)
256 echo 0 $sz linear $BASE_LOOPDUP 0 | dmsetup create --readonly live-base
257 else
258 echo 0 $sz linear $BASE_LOOPDEV 0 | dmsetup create --readonly live-base
259 fi
260 }
261
262 # we might have a genMinInstDelta delta file for anaconda to take advantage of
263 if [ -e /run/initramfs/live/${live_dir}/osmin.img ]; then
264 OSMINSQFS=/run/initramfs/live/${live_dir}/osmin.img
265 # decompress the delta data
266 dd if=$OSMINSQFS of=/run/initramfs/osmin.img 2> /dev/null
267 OSMIN_SQUASHED_LOOPDEV=$( losetup -f )
268 losetup -r $OSMIN_SQUASHED_LOOPDEV /run/initramfs/osmin.img
269 mkdir -m 0755 -p /run/initramfs/squashfs.osmin
270 mount -n -t squashfs -o ro $OSMIN_SQUASHED_LOOPDEV /run/initramfs/squashfs.osmin
271 OSMIN_LOOPDEV=$( losetup -f )
272 losetup -r $OSMIN_LOOPDEV /run/initramfs/squashfs.osmin/osmin
273 umount -l /run/initramfs/squashfs.osmin
274 fi
275
276 # we might have an embedded fs image on squashfs (compressed live)
277 if [ -e /run/initramfs/live/${live_dir}/${squash_image} ]; then
278 SQUASHED="/run/initramfs/live/${live_dir}/${squash_image}"
279 fi
280 if [ -e "$SQUASHED" ]; then
281 if [ -n "$live_ram" ]; then
282 echo 'Copying live image to RAM...' > /dev/kmsg
283 echo ' (this may take a minute)' > /dev/kmsg
284 dd if=$SQUASHED of=/run/initramfs/squashed.img bs=512 2> /dev/null
285 echo 'Done copying live image to RAM.' > /dev/kmsg
286 SQUASHED="/run/initramfs/squashed.img"
287 fi
288
289 SQUASHED_LOOPDEV=$( losetup -f )
290 losetup -r $SQUASHED_LOOPDEV $SQUASHED
291 mkdir -m 0755 -p /run/initramfs/squashfs
292 mount -n -t squashfs -o ro $SQUASHED_LOOPDEV /run/initramfs/squashfs
293
294 if [ -f /run/initramfs/squashfs/LiveOS/rootfs.img ]; then
295 FSIMG="/run/initramfs/squashfs/LiveOS/rootfs.img"
296 elif [ -f /run/initramfs/squashfs/LiveOS/ext3fs.img ]; then
297 FSIMG="/run/initramfs/squashfs/LiveOS/ext3fs.img"
298 fi
299 else
300 # we might have an embedded fs image to use as rootfs (uncompressed live)
301 if [ -e /run/initramfs/live/${live_dir}/rootfs.img ]; then
302 FSIMG="/run/initramfs/live/${live_dir}/rootfs.img"
303 elif [ -e /run/initramfs/live/${live_dir}/ext3fs.img ]; then
304 FSIMG="/run/initramfs/live/${live_dir}/ext3fs.img"
305 fi
306 if [ -n "$live_ram" ]; then
307 echo 'Copying live image to RAM...' > /dev/kmsg
308 echo ' (this may take a minute or so)' > /dev/kmsg
309 dd if=$FSIMG of=/run/initramfs/rootfs.img bs=512 2> /dev/null
310 echo 'Done copying live image to RAM.' > /dev/kmsg
311 FSIMG='/run/initramfs/rootfs.img'
312 fi
313 fi
314
315 if [ -n "$FSIMG" ] ; then
316 if [ -n "$writable_fsimg" ] ; then
317 # mount the provided filesystem read/write
318 echo "Unpacking live filesystem (may take some time)" > /dev/kmsg
319 mkdir -m 0755 /run/initramfs/fsimg/
320 if [ -n "$SQUASHED" ]; then
321 cp -v $FSIMG /run/initramfs/fsimg/rootfs.img
322 else
323 unpack_archive $FSIMG /run/initramfs/fsimg/
324 fi
325 FSIMG=/run/initramfs/fsimg/rootfs.img
326 fi
327 opt=-r
328 # For writable DM images...
329 if [ -z "$SQUASHED" -a -n "$live_ram" -a -z "$overlayfs" ] ||
330 [ -n "$writable_fsimg" ] ||
331 [ "$overlay" = none -o "$overlay" = None -o "$overlay" = NONE ]; then
332 if [ -z "$readonly_overlay" ]; then
333 opt=''
334 setup=rw
335 else
336 setup=yes
337 fi
338 fi
339 BASE_LOOPDEV=$(losetup -f --show $opt $FSIMG)
340 sz=$(blockdev --getsz $BASE_LOOPDEV)
341 if [ "$setup" == rw ]; then
342 echo 0 $sz linear $BASE_LOOPDEV 0 | dmsetup create live-rw
343 else
344 # Add a DM snapshot or OverlayFS for writes.
345 do_live_overlay
346 fi
347 fi
348
349 [ -e "$SQUASHED" ] && [ -z "$overlayfs" ] && umount -l /run/initramfs/squashfs
350
351 if [ -b "$OSMIN_LOOPDEV" ]; then
352 # set up the devicemapper snapshot device, which will merge
353 # the normal live fs image, and the delta, into a minimzied fs image
354 echo "0 $sz snapshot $BASE_LOOPDEV $OSMIN_LOOPDEV P 8" | dmsetup create --readonly live-osimg-min
355 fi
356
357 if [ -n "$reloadsysrootmountunit" ]; then
358 > /xor_overlayfs
359 systemctl daemon-reload
360 fi
361
362 ROOTFLAGS="$(getarg rootflags)"
363
364 if [ -n "$overlayfs" ]; then
365 mkdir -m 0755 /run/rootfsbase
366 if [ -n "$reset_overlay" ] && [ -L /run/overlayfs ]; then
367 ovlfs=$(readlink /run/overlayfs)
368 info "Resetting the OverlayFS overlay directory."
369 rm -r -- ${ovlfs}/* ${ovlfs}/.* >/dev/null 2>&1
370 fi
371 if [ -n "$readonly_overlay" ]; then
372 mkdir -m 0755 /run/rootfsbase-r
373 mount -r $FSIMG /run/rootfsbase-r
374 mount -t overlay LiveOS_rootfs-r -oro,lowerdir=/run/overlayfs-r:/run/rootfsbase-r /run/rootfsbase
375 else
376 mount -r $FSIMG /run/rootfsbase
377 fi
378 if [ -z "$DRACUT_SYSTEMD" ]; then
379 printf 'mount -t overlay LiveOS_rootfs -o%s,%s %s\n' "$ROOTFLAGS" \
380 'lowerdir=/run/rootfsbase,upperdir=/run/overlayfs,workdir=/run/ovlwork' \
381 "$NEWROOT" > $hookdir/mount/01-$$-live.sh
382 fi
383 _dev=/run/rootfsbase
384 else
385 _dev=/dev/mapper/live-rw
386 if [ -z "$DRACUT_SYSTEMD" ]; then
387 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
388 printf 'mount %s /dev/mapper/live-rw %s\n' "$ROOTFLAGS" "$NEWROOT" > $hookdir/mount/01-$$-live.sh
389 fi
390 ln -s $BASE_LOOPDEV /run/rootfsbase
391 fi
392 ln -s $_dev /dev/root
393
394 need_shutdown
395
396 exit 0