Starting ZFS-FUSE up properly
Here is a collection of tips you must pay attention to:
- Put the ZFS PID file in the root filesystem.
- Unset the
LANGenvironment variable. Failure to do so will cause ZFS-FUSE to hang if your/usris on ZFS. - Immunize ZFS-FUSE against the OOM killer. If you don't, then it's very likely that your kernel will kill ZFS-FUSE as soon as things get tight -- and this is something you definitely do not want.
The listing below contains code to do just that. - Remove limits. If you don't remove the limits, ZFS-FUSE will either hang and spin, or consume an inordinate amount of memory (close to two gigabytes).
ulimit -v unlimited ulimit -c 512000 ulimit -l unlimited ulimit -s unlimited
For your convenience, I am attaching the script /sbin/zfsctl which I invoke (with the start argument) in /etc/rc.sysinit after mounting other filesystems, and invoke it (with the stop argument) before killall is executed in the S01killall initscript: It works in Fedora and Ubuntu.
#! /bin/sh
PIDFILE=/.zfs-fuse.pid
LOCKFILE=/var/lock/zfs/zfs_lock
export PATH=/sbin:/bin
unset LANG
ulimit -v unlimited
ulimit -c 512000
ulimit -l unlimited
ulimit -s unlimited
log_action_begin_msg() {
true # echo $*
}
log_action_end_msg() {
true # echo $*
}
do_start() {
test -x /sbin/zfs-fuse || exit 0
PID=`cat "$PIDFILE" 2> /dev/null`
if [ "$PID" != "" ]
then
if kill -0 $PID 2> /dev/null
then
echo "ZFS-FUSE is already running"
exit 3
else
# pid file is stale, we clean up shit
log_action_begin_msg "Cleaning up stale ZFS-FUSE PID files"
rm -f "$PIDFILE"
# /var/run/sendsigs.omit.d/zfs-fuse
log_action_end_msg 0
fi
fi
log_action_begin_msg "Starting ZFS-FUSE process"
zfs-fuse -p "$PIDFILE"
ES_TO_REPORT=$?
if [ 0 = "$ES_TO_REPORT" ]
then
true
else
log_action_end_msg 1 "code $ES_TO_REPORT"
exit 3
fi
for a in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
do
PID=`cat "$PIDFILE" 2> /dev/null`
[ "$PID" != "" ] && break
sleep 1
done
if [ "$PID" = "" ]
then
log_action_end_msg 1 "ZFS-FUSE did not start or create $PIDFILE"
exit 3
else
log_action_end_msg 0
fi
log_action_begin_msg "Immunizing ZFS-FUSE against OOM kills and sendsigs signals"
# mkdir -p /var/run/sendsigs.omit.d
# cp "$PIDFILE" /var/run/sendsigs.omit.d/zfs-fuse
echo -17 > "/proc/$PID/oom_adj"
ES_TO_REPORT=$?
if [ 0 = "$ES_TO_REPORT" ]
then
log_action_end_msg 0
else
log_action_end_msg 1 "code $ES_TO_REPORT"
exit 3
fi
log_action_begin_msg "Mounting ZFS filesystems"
sleep 1
rm -f /var/lib/random-seed
zfs mount -a
ES_TO_REPORT=$?
if [ 0 = "$ES_TO_REPORT" ]
then
log_action_end_msg 0
else
log_action_end_msg 1 "code $ES_TO_REPORT"
#echo "Dropping into a shell for debugging. Post_mountall pending."
#bash
#post_mountall
exit 3
fi
if [ -x /nonexistent -a -x /usr/bin/renice ] ; then # DISABLED
log_action_begin_msg "Increasing ZFS-FUSE priority"
/usr/bin/renice -15 -g $PID > /dev/null
ES_TO_REPORT=$?
if [ 0 = "$ES_TO_REPORT" ]
then
log_action_end_msg 0
else
log_action_end_msg 1 "code $ES_TO_REPORT"
exit 3
fi
true
fi
}
do_stop () {
test -x /sbin/zfs-fuse || exit 0
PID=`cat "$PIDFILE" 2> /dev/null`
if [ "$PID" = "" ] ; then
# no pid file, we exit
exit 0
elif kill -0 $PID 2> /dev/null; then
# pid file and killable, we continue
true
else
# pid file is stale, we clean up shit
log_action_begin_msg "Cleaning up stale ZFS-FUSE PID files"
rm -f "$PIDFILE"
# /var/run/sendsigs.omit.d/zfs-fuse
log_action_end_msg 0
exit 0
fi
log_action_begin_msg "Syncing disks"
sync
log_action_end_msg 0
log_action_begin_msg "Unmounting ZFS filesystems"
zfs unmount -a
ES_TO_REPORT=$?
if [ 0 = "$ES_TO_REPORT" ]
then
log_action_end_msg 0
else
log_action_end_msg 1 "code $ES_TO_REPORT"
exit 3
fi
log_action_begin_msg "Terminating ZFS-FUSE process gracefully"
kill -TERM $PID
for a in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
do
kill -0 $PID 2> /dev/null
[ "$?" != "0" ] && break
sleep 1
done
if kill -0 $PID 2> /dev/null
then
log_action_end_msg 1 "ZFS-FUSE refused to die after 15 seconds"
exit 3
else
rm -f "$PIDFILE"
# /var/run/sendsigs.omit.d/zfs-fuse
log_action_end_msg 0
fi
log_action_begin_msg "Syncing disks again"
sync
log_action_end_msg 0
}
case "$1" in
start)
do_start
;;
stop)
do_stop
;;
status)
PID=`cat "$PIDFILE" 2> /dev/null`
if [ "$PID" = "" ] ; then
echo "ZFS-FUSE is not running"
exit 3
else
if kill -0 $PID
then
echo "ZFS-FUSE is running, pid $PID"
zpool status
exit 0
else
echo "ZFS-FUSE died, PID files stale"
exit 3
fi
fi
;;
restart|reload|force-reload)
echo "Error: argument '$1' not supported" >&2
exit 3
;;
*)
echo "Usage: $0 start|stop|status" >&2
exit 3
;;
esac
:

I'd be happy to know which method works most reliably/portably.