summaryrefslogtreecommitdiffstats
path: root/etc/init.d/zfs.fedora.in
blob: 04f2077ceb418e36283efdb83a09a4fc27347f66 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!/bin/bash
#
# zfs           This script will mount/umount the zfs filesystems.
#
# chkconfig:    2345 01 99
# description:  This script will mount/umount the zfs filesystems during
#               system boot/shutdown.  Configuration of which filesystems
#               should be mounted is handled by the zfs 'mountpoint' and
#               'canmount' properties.  See the zfs(8) man page for details.
#               It is also responsible for all userspace zfs services.
#
### BEGIN INIT INFO
# Provides: zfs
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 1
# Short-Description: Mount/umount the zfs filesystems
# Description: ZFS is an advanced filesystem designed to simplify managing
#              and protecting your data.  This service mounts the ZFS
#              filesystems and starts all related zfs services.
### END INIT INFO

export PATH=/usr/local/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

# Source function library & LSB routines
. /etc/rc.d/init.d/functions

# script variables
RETVAL=0
ZFS="@sbindir@/zfs"
ZPOOL="@sbindir@/zpool"
ZPOOL_CACHE="@sysconfdir@/zfs/zpool.cache"
servicename=zfs
LOCKFILE=/var/lock/subsys/$servicename

# functions
zfs_installed() {
	modinfo zfs > /dev/null 2>&1 || return 5
	$ZPOOL  > /dev/null 2>&1
	[ $? == 127 ] && return 5
	$ZFS    > /dev/null 2>&1
	[ $? == 127 ] && return 5
	return 0
}

reregister_mounts() {
	cat /etc/mtab | while read -r fs mntpnt fstype opts rest ; do
		fs=`printf '%b\n' "$fs"`
		mntpnt=`printf '%b\n' "$mntpnt"`
		if [ "$fstype" == "zfs" ] ; then
			if [ "$mntpnt" == "/" ] ; then
				mount -f -o zfsutil -t zfs --move / /removethismountpointhoweverpossible
				umount --fake /removethismountpointhoweverpossible
			else
				umount --fake "$mntpnt"
			fi
		elif echo "$fs" | grep -q "^/dev/zd" ; then
			if [ "$mntpnt" == "/" ] ; then
				mount -f -t "$fstype" --move / /removethismountpointhoweverpossible
				umount --fake /removethismountpointhoweverpossible
			else
				umount --fake "$mntpnt"
			fi
		fi
	done
	cat /proc/mounts | while read -r fs mntpnt fstype opts rest ; do
		fs=`printf '%b\n' "$fs"`
		mntpnt=`printf '%b\n' "$mntpnt"`
		if [ "$fstype" == "zfs" ] ; then
			mount -f -t zfs -o zfsutil "$fs" "$mntpnt"
		elif echo "$fs" | grep -q "^/dev/zd" ; then
			mount -f -t "$fstype" -o "$opts" "$fs" "$mntpnt"
		fi
	done
}

# i need a bash guru to simplify this, since this is copy and paste, but donno how
# to correctly dereference variable names in bash, or how to do this right

declare -A MTAB
declare -A FSTAB

# first parameter is a regular expression that filters mtab
read_mtab() {
        for fs in "${!MTAB[@]}" ; do unset MTAB["$fs"] ; done
        while read -r fs mntpnt fstype opts blah ; do
                fs=`printf '%b\n' "$fs"`
                MTAB["$fs"]=$mntpnt
        done < <(grep "$1" /etc/mtab)
}

in_mtab() {
        [ "${MTAB[$1]}" != "" ]
        return $?
}

# first parameter is a regular expression that filters fstab
read_fstab() {
        for fs in "${!FSTAB[@]}" ; do unset FSTAB["$fs"] ; done
        while read -r fs mntpnt fstype opts blah ; do
                fs=`printf '%b\n' "$fs"`
                FSTAB["$fs"]=$mntpnt
        done < <(grep "$1" /etc/fstab)
}

in_fstab() {
        [ "${FSTAB[$1]}" != "" ]
        return $?
}

start()
{
	if [ -f "$LOCKFILE" ] ; then return 0 ; fi

	# check if ZFS is installed.  If not, comply to FC standards and bail
	zfs_installed || {
		action $"Checking if ZFS is installed: not installed" /bin/false
		return 5
	}

        # Requires selinux policy which has not been written.
        if [ -r "/selinux/enforce" ] &&
           [ "$(cat /selinux/enforce)" = "1" ]; then
                action $"SELinux ZFS policy required: " /bin/false || return 6
        fi

	# Delay until all required block devices are present.
	udevadm settle

	# load kernel module infrastructure
	if ! grep -q zfs /proc/modules ; then
		action $"Loading kernel ZFS infrastructure: " modprobe zfs || return 5
	fi

	# fix mtab to include already-mounted fs filesystems, in case there are any
	# we ONLY do this if mtab does not point to /proc/mounts
	# which is the case in some systems (systemd may bring that soon)
	if ! readlink /etc/mtab | grep -q /proc ; then
		if grep -qE "(^/dev/zd| zfs )" /proc/mounts ; then
			action $"Registering already-mounted ZFS filesystems and volumes: " reregister_mounts || return 150
		fi
	fi

        if [ -f $ZPOOL_CACHE ] ; then

		echo -n $"Importing ZFS pools not yet imported: "
		$ZPOOL import -c $ZPOOL_CACHE -aN || true # stupid zpool will fail if all pools are already imported
		RETVAL=$?
		if [ $RETVAL -ne 0 ]; then
			failure "Importing ZFS pools not yet imported: "
			return 151
		fi
		success "Importing ZFS pools not yet imported: "

	fi

	action $"Mounting ZFS filesystems not yet mounted: " $ZFS mount -a || return 152

	action $"Exporting ZFS filesystems: " $ZFS share -a || return 153

	read_mtab  "^/dev/zd"
	read_fstab "^/dev/zd"

	template=$"Mounting volume %s registered in fstab: "
	for volume in "${!FSTAB[@]}" ; do
		if in_mtab "$volume" ; then continue ; fi
		string=`printf "$template" "$volume"`
		action "$string" mount "$volume"
	done

	touch "$LOCKFILE"
}

stop()
{
	if [ ! -f "$LOCKFILE" ] ; then return 0 ; fi

	# check if ZFS is installed.  If not, comply to FC standards and bail
	zfs_installed || {
		action $"Checking if ZFS is installed: not installed" /bin/false
		return 5
	}

	# the poweroff of the system takes care of this
	# but it never unmounts the root filesystem itself
	# shit

	action $"Syncing ZFS filesystems: " sync
	     # about the only thing we can do, and then we
	     # hope that the umount process will succeed
	     # unfortunately the umount process does not dismount
	     # the root file system, there ought to be some way
	     # we can tell zfs to just flush anything in memory
	     # when a request to remount,ro comes in

	#echo -n $"Unmounting ZFS filesystems: "
	#$ZFS umount -a
	#RETVAL=$?
	#if [ $RETVAL -ne 0 ]; then
	#	failure

	#	return 8
	#fi
	#success

	rm -f "$LOCKFILE"
}

# See how we are called
case "$1" in
	start)
		start
		RETVAL=$?
		;;
	stop)
		stop
		RETVAL=$?
		;;
	status)
		lsmod | grep -q zfs || RETVAL=3
		$ZPOOL status && echo && $ZFS list || {
			[ -f "$LOCKFILE" ] && RETVAL=2 || RETVAL=4
		}
		;;
	restart)
		stop
		start
		;;
	condrestart)
		if [ -f "$LOCKFILE" ] ; then
			stop
			start
		fi
		;;
	*)
		echo $"Usage: $0 {start|stop|status|restart|condrestart}"
		RETVAL=3
		;;
esac

exit $RETVAL