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