Skip to content

Commit f18a690

Browse files
nabijaczleweliRageLtMan
authored andcommitted
contrib/dracut: 90: mount essential datasets under root
This partly mirrors what the i-t script does (though that mounts all children, recursively) ‒ /etc, /usr, /lib*, and /bin are all essential, if present, to successfully invoke the real init, which will then mount everything else it might need in the right order The following extreme-case set-up boots w/o issues now: / zoot zfs rw,relatime,xattr,noacl ├─/etc zoot/etc zfs rw,relatime,xattr,noacl ├─/usr zoot/usr zfs rw,relatime,xattr,noacl │ └─/usr/local zoot/usr/local zfs rw,relatime,xattr,noacl ├─/var zoot/var zfs rw,relatime,xattr,noacl │ ├─/var/lib zoot/var/lib zfs rw,relatime,xattr,noacl │ ├─/var/log zoot/var/log zfs rw,relatime,xattr,posixacl │ ├─/var/cache zoot/var/cache zfs rw,relatime,xattr,noacl │ └─/var/tmp zoot/var/tmp zfs rw,relatime,xattr,noacl ├─/home zoot/home zfs rw,relatime,xattr,noacl │ └─/home/nab zoot/home/nab zfs rw,relatime,xattr,noacl ├─/boot zoot/boot zfs rw,relatime,xattr,noacl ├─/root zoot/home/root zfs rw,relatime,xattr,noacl ├─/opt zoot/opt zfs rw,relatime,xattr,noacl └─/srv zoot/srv zfs rw,relatime,xattr,noacl Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Ahelenia Ziemiańska <[email protected]> Closes openzfs#11898
1 parent 9696943 commit f18a690

File tree

2 files changed

+101
-19
lines changed

2 files changed

+101
-19
lines changed

contrib/dracut/90zfs/zfs-generator.sh.in

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ GENERATOR_DIR="$1"
1111

1212
[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
1313
[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
14-
1514
command -v getarg >/dev/null 2>&1 || {
1615
[ -n "$debug" ] && echo "zfs-generator: loading Dracut library from $dracutlib" >> /dev/kmsg
1716
. "$dracutlib"
1817
}
1918

19+
. /lib/dracut-zfs-lib.sh
20+
2021
[ -z "$root" ] && root=$(getarg root=)
2122
[ -z "$rootfstype" ] && rootfstype=$(getarg rootfstype=)
2223
[ -z "$rootflags" ] && rootflags=$(getarg rootflags=)
@@ -28,40 +29,84 @@ command -v getarg >/dev/null 2>&1 || {
2829
[ "$rootfstype" != "zfs" ] &&
2930
exit 0
3031

31-
rootfstype=zfs
3232
case ",${rootflags}," in
3333
*,zfsutil,*) ;;
3434
,,) rootflags=zfsutil ;;
3535
*) rootflags="zfsutil,${rootflags}" ;;
3636
esac
3737

38+
if [ "${root}" != "zfs:AUTO" ]; then
39+
root="${root##zfs:}"
40+
root="${root##ZFS=}"
41+
fi
42+
3843
[ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg
3944

40-
[ -d "$GENERATOR_DIR" ] || mkdir "$GENERATOR_DIR"
41-
[ -d "$GENERATOR_DIR"/sysroot.mount.d ] || mkdir "$GENERATOR_DIR"/sysroot.mount.d
4245

46+
mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/initrd-root-fs.target.requires "$GENERATOR_DIR"/dracut-pre-mount.service.d
4347
{
4448
echo "[Unit]"
4549
echo "Before=initrd-root-fs.target"
4650
echo "After=zfs-import.target"
51+
echo
4752
echo "[Mount]"
48-
if [ "${root}" = "zfs:AUTO" ] ; then
53+
if [ "${root}" = "zfs:AUTO" ]; then
4954
echo "PassEnvironment=BOOTFS"
5055
echo 'What=${BOOTFS}'
5156
else
52-
root="${root##zfs:}"
53-
root="${root##ZFS=}"
5457
echo "What=${root}"
5558
fi
56-
echo "Type=${rootfstype}"
59+
echo "Type=zfs"
5760
echo "Options=${rootflags}"
5861
} > "$GENERATOR_DIR"/sysroot.mount.d/zfs-enhancement.conf
62+
ln -fs ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount
63+
64+
65+
if [ "${root}" = "zfs:AUTO" ]; then
66+
{
67+
echo "[Unit]"
68+
echo "Before=initrd-root-fs.target"
69+
echo "After=sysroot.mount"
70+
echo "DefaultDependencies=no"
71+
echo
72+
echo "[Service]"
73+
echo "Type=oneshot"
74+
echo "PassEnvironment=BOOTFS"
75+
echo "ExecStart=/bin/sh -c '" ' \
76+
. /lib/dracut-zfs-lib.sh; \
77+
_zfs_nonroot_necessities_cb() { \
78+
zfs mount | grep -m1 -q "^$1 " && return 0; \
79+
echo "Mounting $1 on /sysroot$2"; \
80+
mount -o zfsutil -t zfs "$1" "/sysroot$2"; \
81+
}; \
82+
for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb;' \
83+
"'"
84+
} > "$GENERATOR_DIR"/zfs-nonroot-necessities.service
85+
ln -fs ../zfs-nonroot-necessities.service "$GENERATOR_DIR"/initrd-root-fs.target.requires/zfs-nonroot-necessities.service
86+
else
87+
# We can solve this statically at generation time, so do!
88+
_zfs_generator_cb() {
89+
dset="${1}"
90+
mpnt="${2}"
91+
unit="sysroot$(echo "$mpnt" | sed 's;/;-;g').mount"
92+
93+
{
94+
echo "[Unit]"
95+
echo "Before=initrd-root-fs.target"
96+
echo "After=sysroot.mount"
97+
echo
98+
echo "[Mount]"
99+
echo "Where=/sysroot${mpnt}"
100+
echo "What=${dset}"
101+
echo "Type=zfs"
102+
echo "Options=zfsutil"
103+
} > "$GENERATOR_DIR/${unit}"
104+
ln -fs ../"${unit}" "$GENERATOR_DIR"/initrd-root-fs.target.requires/"${unit}"
105+
}
106+
107+
for_relevant_root_children "${root}" _zfs_generator_cb
108+
fi
59109

60-
[ -d "$GENERATOR_DIR"/initrd-root-fs.target.requires ] || mkdir -p "$GENERATOR_DIR"/initrd-root-fs.target.requires
61-
ln -s ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount
62-
63-
64-
[ -d "$GENERATOR_DIR"/dracut-pre-mount.service.d ] || mkdir "$GENERATOR_DIR"/dracut-pre-mount.service.d
65110

66111
{
67112
echo "[Unit]"

contrib/dracut/90zfs/zfs-lib.sh.in

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ command -v getargbool >/dev/null || {
2323
OLDIFS="${IFS}"
2424
NEWLINE="
2525
"
26+
TAB=" "
2627

2728
ZPOOL_IMPORT_OPTS=""
2829
if getargbool 0 zfs_force -y zfs.force -y zfsforce ; then
@@ -58,7 +59,7 @@ find_bootfs() {
5859
# import_pool POOL
5960
# imports the given zfs pool if it isn't imported already.
6061
import_pool() {
61-
pool="${1}"
62+
pool="${1}"
6263

6364
if ! zpool list -H "${pool}" > /dev/null 2>&1; then
6465
info "ZFS: Importing pool ${pool}..."
@@ -71,26 +72,62 @@ import_pool() {
7172
return 0
7273
}
7374

75+
_mount_dataset_cb() {
76+
mount -o zfsutil -t zfs "${1}" "${NEWROOT}${2}"
77+
}
78+
7479
# mount_dataset DATASET
7580
# mounts the given zfs dataset.
7681
mount_dataset() {
77-
dataset="${1}"
82+
dataset="${1}"
7883
mountpoint="$(zfs get -H -o value mountpoint "${dataset}")"
84+
ret=0
7985

8086
# We need zfsutil for non-legacy mounts and not for legacy mounts.
8187
if [ "${mountpoint}" = "legacy" ] ; then
82-
mount -t zfs "${dataset}" "${NEWROOT}"
88+
mount -t zfs "${dataset}" "${NEWROOT}" || ret=$?
8389
else
84-
mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}"
90+
mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}" || ret=$?
91+
92+
if [ "$ret" = "0" ]; then
93+
for_relevant_root_children "${dataset}" _mount_dataset_cb || ret=$?
94+
fi
8595
fi
8696

87-
return $?
97+
return ${ret}
98+
}
99+
100+
# for_relevant_root_children DATASET EXEC
101+
# Runs "EXEC dataset mountpoint" for all children of DATASET that are needed for system bringup
102+
# Used by zfs-generator.sh and friends, too!
103+
for_relevant_root_children() {
104+
dataset="${1}"
105+
exec="${2}"
106+
107+
zfs list -t filesystem -Ho name,mountpoint,canmount -r "${dataset}" |
108+
(
109+
_ret=0
110+
while IFS="${TAB}" read -r dataset mountpoint canmount; do
111+
[ "$canmount" != "on" ] && continue
112+
113+
case "$mountpoint" in
114+
/etc|/bin|/lib|/lib??|/libx32|/usr)
115+
# If these aren't mounted we may not be able to get to the real init at all, or pollute the dataset holding the rootfs
116+
"${exec}" "${dataset}" "${mountpoint}" || _ret=$?
117+
;;
118+
*)
119+
# Up to the real init to remount everything else it might need
120+
;;
121+
esac
122+
done
123+
exit ${_ret}
124+
)
88125
}
89126

90127
# export_all OPTS
91128
# exports all imported zfs pools.
92129
export_all() {
93-
opts="${@}"
130+
opts="${@}"
94131
ret=0
95132

96133
IFS="${NEWLINE}"

0 commit comments

Comments
 (0)