#
### BEGIN INIT INFO
# Provides: zfs
-# Required-Start: $local_fs
-# Required-Stop: $local_fs
+# Required-Start:
+# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# filesystems and starts all related zfs services.
### END INIT INFO
-# Source function library.
-. /etc/rc.d/init.d/functions
+export PATH=/usr/local/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
-# Source zfs configuration.
-[ -f /etc/sysconfig/zfs ] && . /etc/sysconfig/zfs
+# Source function library & LSB routines
+. /etc/rc.d/init.d/functions
+# script variables
RETVAL=0
+ZPOOL=zpool
+ZFS=zfs
+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
-LOCKFILE=/var/lock/subsys/zfs
-CACHEFILE=/etc/zfs/zpool.cache
-ZPOOL=/usr/sbin/zpool
-ZFS=/usr/sbin/zfs
+declare -A MTAB
+declare -A FSTAB
-[ -x $ZPOOL ] || exit 1
-[ -x $ZFS ] || exit 2
+# 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()
{
- [ -f $LOCKFILE ] && return 3
-
- # 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 4
+ 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
- # Load the zfs module stack
- /sbin/modprobe zfs
-
- # Ensure / exists in /etc/mtab, if not update mtab accordingly.
- # This should be handled by rc.sysinit but lets be paranoid.
- awk '$2 == "/" { exit 1 }' /etc/mtab
- RETVAL=$?
- if [ $RETVAL -eq 0 ]; then
- /bin/mount -f /
+ # 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
- # Import all pools described by the cache file, and then mount
- # all filesystem based on their properties.
- if [ -f $CACHEFILE ] ; then
- action $"Importing ZFS pools: " \
- $ZPOOL import -c $CACHEFILE -aN 2>/dev/null
- action $"Mounting ZFS filesystems: " \
- $ZFS mount -a
+ if [ -f /etc/zfs/zpool.cache ] ; then
+
+ echo -n $"Importing ZFS pools not yet imported: "
+ $ZPOOL import -c /etc/zfs/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
- touch $LOCKFILE
-}
+ action $"Mounting ZFS filesystems not yet mounted: " $ZFS mount -a || return 152
-stop()
-{
- [ ! -f $LOCKFILE ] && return 3
+ action $"Exporting ZFS filesystems: " $ZFS share -a || return 153
- action $"Unmounting ZFS filesystems: " $ZFS umount -a
+ read_mtab "^/dev/zd"
+ read_fstab "^/dev/zd"
- rm -f $LOCKFILE
+ 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"
}
-status()
+stop()
{
- [ ! -f $LOCKFILE ] && return 3
-
- $ZPOOL status && echo && $ZPOOL list
+ 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=$?
;;
status)
- status
- RETVAL=$?
+ 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
+ if [ -f "$LOCKFILE" ] ; then
stop
start
fi
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart}"
+ RETVAL=3
;;
esac