aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/dracut/90zfs/zfs-lib.sh.in
blob: a8903a5e1b173b16234a7af1f405d455b6eefd0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/bin/sh
# shellcheck disable=SC2034

command -v getarg >/dev/null || . /lib/dracut-lib.sh || . /usr/lib/dracut/modules.d/99base/dracut-lib.sh
command -v getargbool >/dev/null || {
    # Compatibility with older Dracut versions.
    # With apologies to the Dracut developers.
    getargbool() {
        _default="$1"; shift
        ! _b=$(getarg "$@") && [ -z "$_b" ] && _b="$_default"
        if [ -n "$_b" ]; then
            [ "$_b" = "0" ] && return 1
            [ "$_b" = "no" ] && return 1
            [ "$_b" = "off" ] && return 1
        fi
        return 0
    }
}

TAB="	"

ZPOOL_IMPORT_OPTS=
if getargbool 0 zfs_force -y zfs.force -y zfsforce; then
    warn "ZFS: Will force-import pools if necessary."
    ZPOOL_IMPORT_OPTS=-f
fi

_mount_dataset_cb() {
    # shellcheck disable=SC2154
    mount -o zfsutil -t zfs "${1}" "${NEWROOT}${2}"
}

# mount_dataset DATASET
#   mounts the given zfs dataset.
mount_dataset() {
    dataset="${1}"
    mountpoint="$(zfs get -H -o value mountpoint "${dataset}")"
    ret=0

    # We need zfsutil for non-legacy mounts and not for legacy mounts.
    if [ "${mountpoint}" = "legacy" ] ; then
        mount -t zfs "${dataset}" "${NEWROOT}" || ret=$?
    else
        mount -o zfsutil -t zfs "${dataset}" "${NEWROOT}" || ret=$?

        if [ "$ret" = "0" ]; then
            for_relevant_root_children "${dataset}" _mount_dataset_cb || ret=$?
        fi
    fi

    return "${ret}"
}

# for_relevant_root_children DATASET EXEC
#   Runs "EXEC dataset mountpoint" for all children of DATASET that are needed for system bringup
#   Used by zfs-generator.sh and friends, too!
for_relevant_root_children() {
    dataset="${1}"
    exec="${2}"

    zfs list -t filesystem -Ho name,mountpoint,canmount -r "${dataset}" |
        (
            _ret=0
            while IFS="${TAB}" read -r dataset mountpoint canmount; do
                [ "$canmount" != "on" ] && continue

                case "$mountpoint" in
                    /etc|/bin|/lib|/lib??|/libx32|/usr)
                        # 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
                        "${exec}" "${dataset}" "${mountpoint}" || _ret=$?
                        ;;
                    *)
                        # Up to the real init to remount everything else it might need
                        ;;
                esac
            done
            exit "${_ret}"
        )
}

# Parse root=, rootfstype=, return them decoded and normalised to zfs:AUTO for auto, plain dset for explicit
#
# True if ZFS-on-root, false if we shouldn't
#
# Supported values:
#   root=
#   root=zfs
#   root=zfs:
#   root=zfs:AUTO
#
#   root=ZFS=data/set
#   root=zfs:data/set
#   root=zfs:ZFS=data/set (as a side-effect; allowed but undocumented)
#
#   rootfstype=zfs AND root=data/set <=> root=data/set
#   rootfstype=zfs AND root=         <=> root=zfs:AUTO
#
# '+'es in explicit dataset decoded to ' 's.
decode_root_args() {
    if [ -n "$rootfstype" ]; then
        [ "$rootfstype" = zfs ]
        return
    fi

    root=$(getarg root=)
    rootfstype=$(getarg rootfstype=)

    # shellcheck disable=SC2249
    case "$root" in
        ""|zfs|zfs:|zfs:AUTO)
            root=zfs:AUTO
            rootfstype=zfs
            return 0
            ;;

        ZFS=*|zfs:*)
            root="${root#zfs:}"
            root="${root#ZFS=}"
            root=$(echo "$root" | tr '+' ' ')
            rootfstype=zfs
            return 0
            ;;
    esac

    if [ "$rootfstype" = "zfs" ]; then
        case "$root" in
            "") root=zfs:AUTO ;;
            *)  root=$(echo "$root" | tr '+' ' ') ;;
        esac
        return 0
    fi

    return 1
}