]> git.ipfire.org Git - thirdparty/dracut.git/blob - modules.d/90dmsquash-live/dmsquash-live-root.sh
0c5e010ec192aef85b333835dfc2fd676629fe7c
[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 for the ro base of overlayed file systems.
254 if [ -z "$overlayfs" ]; then
255 echo 0 $sz linear $BASE_LOOPDEV 0 | dmsetup create --readonly live-base
256 fi
257 ln -s $BASE_LOOPDEV /dev/live-base
258 }
259
260 # we might have a genMinInstDelta delta file for anaconda to take advantage of
261 if [ -e /run/initramfs/live/${live_dir}/osmin.img ]; then
262 OSMINSQFS=/run/initramfs/live/${live_dir}/osmin.img
263 # decompress the delta data
264 dd if=$OSMINSQFS of=/run/initramfs/osmin.img 2> /dev/null
265 OSMIN_SQUASHED_LOOPDEV=$( losetup -f )
266 losetup -r $OSMIN_SQUASHED_LOOPDEV /run/initramfs/osmin.img
267 mkdir -m 0755 -p /run/initramfs/squashfs.osmin
268 mount -n -t squashfs -o ro $OSMIN_SQUASHED_LOOPDEV /run/initramfs/squashfs.osmin
269 OSMIN_LOOPDEV=$( losetup -f )
270 losetup -r $OSMIN_LOOPDEV /run/initramfs/squashfs.osmin/osmin
271 umount -l /run/initramfs/squashfs.osmin
272 fi
273
274 # we might have an embedded fs image on squashfs (compressed live)
275 if [ -e /run/initramfs/live/${live_dir}/${squash_image} ]; then
276 SQUASHED="/run/initramfs/live/${live_dir}/${squash_image}"
277 fi
278 if [ -e "$SQUASHED" ]; then
279 if [ -n "$live_ram" ]; then
280 echo 'Copying live image to RAM...' > /dev/kmsg
281 echo ' (this may take a minute)' > /dev/kmsg
282 dd if=$SQUASHED of=/run/initramfs/squashed.img bs=512 2> /dev/null
283 echo 'Done copying live image to RAM.' > /dev/kmsg
284 SQUASHED="/run/initramfs/squashed.img"
285 fi
286
287 SQUASHED_LOOPDEV=$( losetup -f )
288 losetup -r $SQUASHED_LOOPDEV $SQUASHED
289 mkdir -m 0755 -p /run/initramfs/squashfs
290 mount -n -t squashfs -o ro $SQUASHED_LOOPDEV /run/initramfs/squashfs
291
292 if [ -d /run/initramfs/squashfs/LiveOS ]; then
293 if [ -f /run/initramfs/squashfs/LiveOS/rootfs.img ]; then
294 FSIMG="/run/initramfs/squashfs/LiveOS/rootfs.img"
295 elif [ -f /run/initramfs/squashfs/LiveOS/ext3fs.img ]; then
296 FSIMG="/run/initramfs/squashfs/LiveOS/ext3fs.img"
297 fi
298 elif [ -d /run/initramfs/squashfs/proc ]; then
299 FSIMG=$SQUASHED
300 if [ -z "$overlayfs" ]; then
301 overlayfs="yes"
302 [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="yes"
303 fi
304 else
305 die "Failed to find a root filesystem in $SQUASHED."
306 exit 1
307 fi
308 else
309 # we might have an embedded fs image to use as rootfs (uncompressed live)
310 if [ -e /run/initramfs/live/${live_dir}/rootfs.img ]; then
311 FSIMG="/run/initramfs/live/${live_dir}/rootfs.img"
312 elif [ -e /run/initramfs/live/${live_dir}/ext3fs.img ]; then
313 FSIMG="/run/initramfs/live/${live_dir}/ext3fs.img"
314 fi
315 if [ -n "$live_ram" ]; then
316 echo 'Copying live image to RAM...' > /dev/kmsg
317 echo ' (this may take a minute or so)' > /dev/kmsg
318 dd if=$FSIMG of=/run/initramfs/rootfs.img bs=512 2> /dev/null
319 echo 'Done copying live image to RAM.' > /dev/kmsg
320 FSIMG='/run/initramfs/rootfs.img'
321 fi
322 fi
323
324 if [ -n "$FSIMG" ]; then
325 if [ -n "$writable_fsimg" ]; then
326 # mount the provided filesystem read/write
327 echo "Unpacking live filesystem (may take some time)" > /dev/kmsg
328 mkdir -m 0755 /run/initramfs/fsimg/
329 if [ -n "$SQUASHED" ]; then
330 cp -v $FSIMG /run/initramfs/fsimg/rootfs.img
331 else
332 unpack_archive $FSIMG /run/initramfs/fsimg/
333 fi
334 FSIMG=/run/initramfs/fsimg/rootfs.img
335 fi
336 opt=-r
337 # For writable DM images...
338 if [ -z "$SQUASHED" -a -n "$live_ram" -a -z "$overlayfs" ] ||
339 [ -n "$writable_fsimg" ] ||
340 [ "$overlay" = none -o "$overlay" = None -o "$overlay" = NONE ]; then
341 if [ -z "$readonly_overlay" ]; then
342 opt=''
343 setup=rw
344 else
345 setup=yes
346 fi
347 fi
348 if [ "$FSIMG" = "$SQUASHED" ]; then
349 BASE_LOOPDEV=$SQUASHED_LOOPDEV
350 else
351 BASE_LOOPDEV=$(losetup -f --show $opt $FSIMG)
352 sz=$(blockdev --getsz $BASE_LOOPDEV)
353 fi
354 if [ "$setup" = rw ]; then
355 echo 0 $sz linear $BASE_LOOPDEV 0 | dmsetup create live-rw
356 else
357 # Add a DM snapshot or OverlayFS for writes.
358 do_live_overlay
359 fi
360 fi
361
362 if [ -b "$OSMIN_LOOPDEV" ]; then
363 # set up the devicemapper snapshot device, which will merge
364 # the normal live fs image, and the delta, into a minimzied fs image
365 echo "0 $sz snapshot $BASE_LOOPDEV $OSMIN_LOOPDEV P 8" | dmsetup create --readonly live-osimg-min
366 fi
367
368 if [ -n "$reloadsysrootmountunit" ]; then
369 > /xor_overlayfs
370 systemctl daemon-reload
371 fi
372
373 ROOTFLAGS="$(getarg rootflags)"
374
375 if [ -n "$overlayfs" ]; then
376 mkdir -m 0755 /run/rootfsbase
377 if [ -n "$reset_overlay" ] && [ -L /run/overlayfs ]; then
378 ovlfs=$(readlink /run/overlayfs)
379 info "Resetting the OverlayFS overlay directory."
380 rm -r -- ${ovlfs}/* ${ovlfs}/.* >/dev/null 2>&1
381 fi
382 if [ -n "$readonly_overlay" ]; then
383 mkdir -m 0755 /run/rootfsbase-r
384 mount -r $FSIMG /run/rootfsbase-r
385 mount -t overlay LiveOS_rootfs-r -oro,lowerdir=/run/overlayfs-r:/run/rootfsbase-r /run/rootfsbase
386 else
387 mount -r $FSIMG /run/rootfsbase
388 fi
389 if [ -z "$DRACUT_SYSTEMD" ]; then
390 printf 'mount -t overlay LiveOS_rootfs -o%s,%s %s\n' "$ROOTFLAGS" \
391 'lowerdir=/run/rootfsbase,upperdir=/run/overlayfs,workdir=/run/ovlwork' \
392 "$NEWROOT" > $hookdir/mount/01-$$-live.sh
393 fi
394 else
395 if [ -z "$DRACUT_SYSTEMD" ]; then
396 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
397 printf 'mount %s /dev/mapper/live-rw %s\n' "$ROOTFLAGS" "$NEWROOT" > $hookdir/mount/01-$$-live.sh
398 fi
399 fi
400 [ -e "$SQUASHED" ] && umount -l /run/initramfs/squashfs
401
402 ln -s null /dev/root
403
404 need_shutdown
405
406 exit 0
407