--- /dev/null
+diff --git a/sheep/sheep.c b/sheep/sheep.c
+index 7d1e853..675e729 100644
+--- a/sheep/sheep.c
++++ b/sheep/sheep.c
+@@ -19,6 +19,10 @@
+ #include <signal.h>
+ #include <linux/limits.h>
+ #include <sys/syslog.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <errno.h>
+
+ #include "sheep_priv.h"
+ #include "trace/trace.h"
+@@ -44,10 +48,11 @@ static struct option const long_options[] = {
+ {"vnodes", required_argument, NULL, 'v'},
+ {"enable-cache", no_argument, NULL, 'w'},
+ {"zone", required_argument, NULL, 'z'},
++ {"pidfile", required_argument, NULL, 'P'},
+ {NULL, 0, NULL, 0},
+ };
+
+-static const char *short_options = "c:dDfghl:op:v:wy:z:";
++static const char *short_options = "c:dDfghl:op:P:v:wy:z:";
+
+ static void usage(int status)
+ {
+@@ -68,6 +73,7 @@ Options:\n\
+ -l, --loglevel specify the level of logging detail\n\
+ -o, --stdout log to stdout instead of shared logger\n\
+ -p, --port specify the TCP port on which to listen\n\
++ -P, --pidfile create a pid file\n\
+ -v, --vnodes specify the number of virtual nodes\n\
+ -w, --enable-cache enable object cache\n\
+ -y, --myaddr specify the address advertised to other sheep\n\
+@@ -91,6 +97,31 @@ Available log levels:\n\
+ 7 SDOG_DEBUG debugging messages\n");
+ }
+
++static int create_pidfile(const char *filename)
++{
++ int fd = -1;
++ int len;
++ char buffer[128];
++
++ if ((fd = open(filename, O_RDWR|O_CREAT|O_SYNC, 0600)) == -1) {
++ return -1;
++ }
++
++ if (lockf(fd, F_TLOCK, 0) == -1) {
++ close(fd);
++ return -1;
++ }
++
++ len = snprintf(buffer, sizeof(buffer), "%d\n", getpid());
++ if (write(fd, buffer, len) != len) {
++ close(fd);
++ return -1;
++ }
++
++ /* keep pidfile open & locked forever */
++ return 0;
++}
++
+ static struct cluster_info __sys;
+ struct cluster_info *sys = &__sys;
+
+@@ -110,6 +141,7 @@ int main(int argc, char **argv)
+ char *p;
+ struct cluster_driver *cdrv;
+ int enable_write_cache = 0; /* disabled by default */
++ char *pid_file = NULL;
+
+ signal(SIGPIPE, SIG_IGN);
+
+@@ -124,6 +156,9 @@ int main(int argc, char **argv)
+ exit(1);
+ }
+ break;
++ case 'P':
++ pid_file = optarg;
++ break;
+ case 'f':
+ is_daemon = 0;
+ break;
+@@ -264,6 +299,11 @@ int main(int argc, char **argv)
+ if (ret)
+ exit(1);
+
++ if (pid_file && (create_pidfile(pid_file) != 0)) {
++ fprintf(stderr, "failed to pid file '%s' - %s\n", pid_file, strerror(errno));
++ exit(1);
++ }
++
+ if (chdir(dir) < 0) {
+ fprintf(stderr, "failed to chdir to %s: %m\n", dir);
+ exit(1);
+@@ -279,5 +319,9 @@ int main(int argc, char **argv)
+ leave_cluster();
+ log_close();
+
++ if (pid_file) {
++ unlink(pid_file);
++ }
++
+ return 0;
+ }
[ -x $DAEMON ] || exit 0
# Defaults
-SHEEPDOG_PATH="/var/lib/sheepdog"
+SHEEPDOG_START_SEQUENCE="_1"
+SHEEPDOG_DEAMON_ARGS_1=""
+SHEEPDOG_PATH_1="/var/lib/sheepdog/disc1"
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
{
mkdir -p /var/run
- mkdir -p $SHEEPDOG_PATH
-
- # Return
+ # Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
- status "$DAEMON" >/dev/null && return 1
+ for SHEEP in $SHEEPDOG_START_SEQUENCE; do
+ eval DAEMON_ARGS=\$SHEEPDOG_DEAMON_ARGS$SHEEP
+ eval SHEEPDOG_PATH=\$SHEEPDOG_PATH$SHEEP
+ eval PIDFILE=/var/run/$NAME$SHEEP.pid
+
+ mkdir -p $SHEEPDOG_PATH
+
+ status_of_proc -p ${PIDFILE} $DAEMON "$NAME" >/dev/null && continue
- start-stop-daemon --start --quiet --exec $DAEMON -- $DAEMON_ARGS $SHEEPDOG_PATH || return 2
+ start-stop-daemon --start --quiet --pidfile ${PIDFILE} --exec $DAEMON -- --pidfile ${PIDFILE} $DAEMON_ARGS $SHEEPDOG_PATH || return 2
+ done
+
+ return 0
}
#
# 2 if daemon could not be stopped
# other if a failure occurred
- status "$DAEMON" >/dev/null || return 1
-
- start-stop-daemon --stop --retry=TERM/20/KILL/5 --exec $DAEMON
- RETVAL="$?"
- [ "$RETVAL" = 2 ] && return 2
-
- # Many daemons don't delete their pidfiles when they exit.
- # rm -f $PIDFILE
+ RETVAL=0
+ for SHEEP in $SHEEPDOG_START_SEQUENCE; do
+ eval DAEMON_ARGS=\$SHEEPDOG_DEAMON_ARGS$SHEEP
+ eval SHEEPDOG_PATH=\$SHEEPDOG_PATH$SHEEP
+ eval PIDFILE=/var/run/$NAME$SHEEP.pid
+ start-stop-daemon --stop --oknodo --retry=TERM/20/KILL/5 --quiet --pidfile ${PIDFILE} --exec $DAEMON || RETVAL=2
+ done
return "$RETVAL"
}
0|1) log_end_msg 0 ;;
2) log_end_msg 1 ;;
esac
+
;;
status)
- status "$DAEMON" && exit 0 || exit $?
+ for SHEEP in $SHEEPDOG_START_SEQUENCE; do
+ eval DAEMON_ARGS=\$SHEEPDOG_DEAMON_ARGS$SHEEP
+ eval SHEEPDOG_PATH=\$SHEEPDOG_PATH$SHEEP
+ eval PIDFILE=/var/run/$NAME$SHEEP.pid
+ status_of_proc -p ${PIDFILE} $DAEMON "$NAME${SHEEP}" || exit $?
+ done
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"