[sheepdog] [PATCH v5] sheep: implement a correct mutex of a base directory
Hitoshi Mitake
mitake.hitoshi at gmail.com
Tue Apr 30 02:14:19 CEST 2013
Current lockf() usage in lock_base_dir() is invalid bacause sheep
calls daemon(3) after the lockf(). daemon(3) forks internally and a
parent process exits immediately. In a case of sheep, daemon() must be
called after locking base dir so the lock owner, parent process, exits
and the lock will be released even though the child process is
running. This is the reason current lock_base_dir() doesn't work
well. And it causes writing logs to sheep.log from multiple
sheeps. This phenomenon is very confusing and should be avoided.
This patch implement custom function for daemonizing,
lock_and_daemon(). And mutex of base directory is done in
it. lock_and_daemon() does mutex between fork() and closing fd 0, 1,
and 2, so it can report the failure of mutexing base directory to
stderr.
Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
v5: update the commit log
v4: also lock file when sheep runs in foreground
v3: implement custom function for daemonizing and do mutex in it
v2: call exit_handler() from crash_handler() too
sheep/sheep.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++-
sheep/sheep_priv.h | 1 +
sheep/store.c | 4 ++--
3 files changed, 63 insertions(+), 3 deletions(-)
diff --git a/sheep/sheep.c b/sheep/sheep.c
index 95bfa9a..bbfe772 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -390,6 +390,65 @@ static void check_host_env(void)
r.rlim_cur);
}
+static int lock_and_daemon(bool daemonize, const char *base_dir)
+{
+ int ret, devnull_fd;
+
+ if (daemonize) {
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ panic("fork() failed during daemonize: %m");
+ break;
+ default:
+ exit(0);
+ break;
+ }
+
+ if (setsid() == -1)
+ panic("becoming a leader of a new session failed: %m");
+
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ panic("fork() failed during daemonize: %m");
+ break;
+ default:
+ exit(0);
+ break;
+ }
+
+ if (chdir("/"))
+ panic("chdir to / failed: %m");
+
+ devnull_fd = open("/dev/null", O_RDWR);
+ if (devnull_fd < 0)
+ panic("opening /dev/null failed: %m");
+ }
+
+ ret = lock_base_dir(base_dir);
+ if (ret < 0) {
+ sd_eprintf("locking directory: %s failed", base_dir);
+ return -1;
+ }
+
+ if (daemonize) {
+ /*
+ * now we can use base_dir/sheep.log for logging error messages,
+ * we can close 0, 1, and 2 safely
+ */
+ dup2(devnull_fd, 0);
+ dup2(devnull_fd, 1);
+ dup2(devnull_fd, 2);
+
+ close(devnull_fd);
+ }
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
int ch, longindex, ret, port = SD_LISTEN_PORT, io_port = SD_LISTEN_PORT;
@@ -582,7 +641,7 @@ int main(int argc, char **argv)
srandom(port);
- if (is_daemon && daemon(0, 0))
+ if (lock_and_daemon(is_daemon, dirp))
exit(1);
ret = log_init(program_name, LOG_SPACE_SIZE, to_stdout, log_level,
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index b9d6f97..89247a9 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -250,6 +250,7 @@ int init_store_driver(bool is_gateway);
int init_global_pathnames(const char *d, char *);
int init_base_path(const char *dir);
int init_disk_space(const char *d);
+int lock_base_dir(const char *d);
int fill_vdi_copy_list(void *data);
int get_vdi_copy_number(uint32_t vid);
diff --git a/sheep/store.c b/sheep/store.c
index ec3451c..6590664 100644
--- a/sheep/store.c
+++ b/sheep/store.c
@@ -185,7 +185,7 @@ uint32_t get_latest_epoch(void)
return epoch;
}
-static int lock_base_dir(const char *d)
+int lock_base_dir(const char *d)
{
#define LOCK_PATH "/lock"
char *lock_path;
@@ -224,7 +224,7 @@ int init_base_path(const char *d)
return -1;
}
- return lock_base_dir(d);
+ return 0;
}
/*
--
1.7.10.rc0.41.gfa678
More information about the sheepdog
mailing list