1#!/bin/sh
2# shellcheck disable=SC2016,SC1004
3
4grep -wq debug /proc/cmdline && debug=1
5[ -n "$debug" ] && echo "zfs-generator: starting" >> /dev/kmsg
6
7GENERATOR_DIR="$1"
8[ -n "$GENERATOR_DIR" ] || {
9    echo "zfs-generator: no generator directory specified, exiting" >> /dev/kmsg
10    exit 1
11}
12
13[ -f /lib/dracut-lib.sh ] && dracutlib=/lib/dracut-lib.sh
14[ -f /usr/lib/dracut/modules.d/99base/dracut-lib.sh ] && dracutlib=/usr/lib/dracut/modules.d/99base/dracut-lib.sh
15command -v getarg >/dev/null 2>&1 || {
16    [ -n "$debug" ] && echo "zfs-generator: loading Dracut library from $dracutlib" >> /dev/kmsg
17    . "$dracutlib"
18}
19
20. /lib/dracut-zfs-lib.sh
21
22[ -z "$root" ]       && root=$(getarg root=)
23[ -z "$rootfstype" ] && rootfstype=$(getarg rootfstype=)
24[ -z "$rootflags" ]  && rootflags=$(getarg rootflags=)
25
26# If root is not ZFS= or zfs: or rootfstype is not zfs
27# then we are not supposed to handle it.
28[ "${root##zfs:}" = "${root}" ] &&
29	[ "${root##ZFS=}" = "${root}" ] &&
30	[ "$rootfstype" != "zfs" ] &&
31	exit 0
32
33case ",${rootflags}," in
34	*,zfsutil,*) ;;
35	,,)	rootflags=zfsutil ;;
36	*)	rootflags="zfsutil,${rootflags}" ;;
37esac
38
39if [ "${root}" != "zfs:AUTO" ]; then
40  root="${root##zfs:}"
41  root="${root##ZFS=}"
42fi
43
44[ -n "$debug" ] && echo "zfs-generator: writing extension for sysroot.mount to $GENERATOR_DIR/sysroot.mount.d/zfs-enhancement.conf" >> /dev/kmsg
45
46
47mkdir -p "$GENERATOR_DIR"/sysroot.mount.d "$GENERATOR_DIR"/initrd-root-fs.target.requires "$GENERATOR_DIR"/dracut-pre-mount.service.d
48{
49    echo "[Unit]"
50    echo "Before=initrd-root-fs.target"
51    echo "After=zfs-import.target"
52    echo
53    echo "[Mount]"
54    if [ "${root}" = "zfs:AUTO" ]; then
55      echo "PassEnvironment=BOOTFS"
56      echo 'What=${BOOTFS}'
57    else
58      echo "What=${root}"
59    fi
60    echo "Type=zfs"
61    echo "Options=${rootflags}"
62} > "$GENERATOR_DIR"/sysroot.mount.d/zfs-enhancement.conf
63ln -fs ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount
64
65
66if [ "${root}" = "zfs:AUTO" ]; then
67  {
68      echo "[Unit]"
69      echo "Before=initrd-root-fs.target"
70      echo "After=sysroot.mount"
71      echo "DefaultDependencies=no"
72      echo
73      echo "[Service]"
74      echo "Type=oneshot"
75      echo "PassEnvironment=BOOTFS"
76      echo "ExecStart=/bin/sh -c '" '                                        \
77        . /lib/dracut-zfs-lib.sh;                                            \
78        _zfs_nonroot_necessities_cb() {                                      \
79            zfs mount | grep -m1 -q "^$1 " && return 0;                      \
80            echo "Mounting $1 on /sysroot$2";                                \
81            mount -o zfsutil -t zfs "$1" "/sysroot$2";                       \
82        };                                                                   \
83        for_relevant_root_children "${BOOTFS}" _zfs_nonroot_necessities_cb;' \
84      "'"
85  } > "$GENERATOR_DIR"/zfs-nonroot-necessities.service
86  ln -fs ../zfs-nonroot-necessities.service "$GENERATOR_DIR"/initrd-root-fs.target.requires/zfs-nonroot-necessities.service
87else
88  # We can solve this statically at generation time, so do!
89  _zfs_generator_cb() {
90      dset="${1}"
91      mpnt="${2}"
92      unit="sysroot$(echo "$mpnt" | sed 's;/;-;g').mount"
93
94      {
95          echo "[Unit]"
96          echo "Before=initrd-root-fs.target"
97          echo "After=sysroot.mount"
98          echo
99          echo "[Mount]"
100          echo "Where=/sysroot${mpnt}"
101          echo "What=${dset}"
102          echo "Type=zfs"
103          echo "Options=zfsutil"
104      } > "$GENERATOR_DIR/${unit}"
105      ln -fs ../"${unit}" "$GENERATOR_DIR"/initrd-root-fs.target.requires/"${unit}"
106  }
107
108  for_relevant_root_children "${root}" _zfs_generator_cb
109fi
110
111
112{
113    echo "[Unit]"
114    echo "After=zfs-import.target"
115} > "$GENERATOR_DIR"/dracut-pre-mount.service.d/zfs-enhancement.conf
116
117[ -n "$debug" ] && echo "zfs-generator: finished" >> /dev/kmsg
118
119exit 0
120