]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - etc/systemd/system-generators/zfs-mount-generator.in
systemd mount generator and tracking ZEDLET
[FreeBSD/FreeBSD.git] / etc / systemd / system-generators / zfs-mount-generator.in
1 #!/bin/sh
2
3 # zfs-mount-generator - generates systemd mount units for zfs
4 # Copyright (c) 2017 Antonio Russo <antonio.e.russo@gmail.com>
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining
7 # a copy of this software and associated documentation files (the
8 # "Software"), to deal in the Software without restriction, including
9 # without limitation the rights to use, copy, modify, merge, publish,
10 # distribute, sublicense, and/or sell copies of the Software, and to
11 # permit persons to whom the Software is furnished to do so, subject to
12 # the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 set -ef
26
27 FSLIST="@sysconfdir@/zfs/zfs-list.cache"
28
29 [ -d "${FSLIST}" ] || exit 0
30
31 do_fail() {
32   printf 'zfs-mount-generator.sh: %s\n' "$*" > /dev/kmsg
33   exit 1
34 }
35
36 # see systemd.generator
37 if [ $# -eq 0 ] ; then
38   dest_norm="/tmp"
39 elif [ $# -eq 3 ] ; then
40   dest_norm="${1}"
41 else
42   do_fail "zero or three arguments required"
43 fi
44
45 # For ZFSs marked "auto", a dependency is created for local-fs.target. To
46 # avoid regressions, this dependency is reduced to "wants" rather than
47 # "requires". **THIS MAY CHANGE**
48 req_dir="${dest_norm}/local-fs.target.wants/"
49 mkdir -p "${req_dir}"
50
51 # All needed information about each ZFS is available from
52 # zfs list -H -t filesystem -oname,mountpoint,canmount
53 # cached in $FSLIST, and each line is processed by the following function:
54
55 process_line() {
56
57   # Check for canmount=off .
58   if [ "${3}" = "off" ] ; then
59     return
60   elif [ "${3}" = "noauto" ] ; then
61     # Don't let a noauto marked mountpoint block an "auto" market mountpoint
62     return
63   elif [ "${3}" = "on" ] ; then
64     : # This is OK
65   else
66     do_fail "invalid canmount"
67   fi
68
69   # Check for legacy and blank mountpoints.
70   if [ "${2}" = "legacy" ] ; then
71     return
72   elif [ "${2}" = "none" ] ; then
73     return
74   elif [ "${2%"${2#?}"}" != "/" ] ; then
75     do_fail "invalid mountpoint $*"
76   fi
77
78   # Escape the mountpoint per systemd policy.
79   mountfile="$(systemd-escape "${2#?}").mount"
80
81   # If the mountpoint has already been created, give it precedence.
82   if [ -e "${dest_norm}/${mountfile}" ] ; then
83     printf 'zfs-mount-generator.sh: %s.mount already exists\n' "${2}" \
84       >/dev/kmsg
85     return
86   fi
87
88   # By ordering before zfs-mount.service, we avoid race conditions.
89   cat > "${dest_norm}/${mountfile}" << EOF
90 # Automatically generated by zfs-mount-generator
91
92 [Unit]
93 SourcePath=${FSLIST}/${cachefile}
94 Documentation=man:zfs-mount-generator(8)
95 Before=local-fs.target zfs-mount.service
96 After=zfs-import.target
97 Wants=zfs-import.target
98
99 [Mount]
100 Where=${2}
101 What=${1}
102 Type=zfs
103 Options=zfsutil,auto
104 EOF
105
106   # Finally, create the appropriate dependencies based on the ZFS properties.
107   [ "$3" = "on" ] & ln -s "../${mountfile}" "${req_dir}"
108 }
109
110 # Feed each line into process_line
111 for cachefile in $(ls "${FSLIST}") ; do
112   while read -r fs ; do
113     process_line $fs
114   done < "${FSLIST}/${cachefile}"
115 done