Signed-off-by: Liu Yuan <namei.u...@gmail.com> --- sheep/cluster/local.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-)
diff --git a/sheep/cluster/local.c b/sheep/cluster/local.c index 6d0af68..c9c0ede 100644 --- a/sheep/cluster/local.c +++ b/sheep/cluster/local.c @@ -16,6 +16,7 @@ #include <sys/file.h> #include <signal.h> #include <fcntl.h> +#include <limits.h> #include "cluster.h" #include "event.h" @@ -27,6 +28,10 @@ #define LOCAL_MAX_NODES 1024 static const char *shmfile = "/tmp/sheepdog_shm"; +static const char *lockdir = "/tmp/sheepdog_locks/"; +/* we have to use sd_lock because flock isn't thread exclusive */ +static struct sd_lock lock = SD_LOCK_INITIALIZER; + static int shmfd; static int sigfd; static int block_event_pos; @@ -99,14 +104,25 @@ static inline void node_insert(struct sd_node *new, struct rb_root *root) panic("insert duplicate %s", node_to_str(new)); } +static int xflock(int fd, int operation) +{ + int ret; + + do { + ret = flock(fd, operation); + } while (ret < 0 && (errno == EAGAIN || errno == EINTR)); + + return ret; +} + static void shm_queue_lock(void) { - flock(shmfd, LOCK_EX); + xflock(shmfd, LOCK_EX); } static void shm_queue_unlock(void) { - flock(shmfd, LOCK_UN); + xflock(shmfd, LOCK_UN); } static size_t get_nodes(struct local_node *n) @@ -544,15 +560,51 @@ static int local_init(const char *option) return -1; } + ret = xmkdir(lockdir, sd_def_dmode); + if (ret < 0) { + sd_err("failed to create lockdir %s, %m", lockdir); + return -1; + } + + ret = purge_directory(lockdir); + if (ret < 0) { + sd_err("failed to purge lockdir %s, %m", lockdir); + return -1; + } + return 0; } static void local_lock(uint64_t lock_id) { + char path[PATH_MAX]; + int fd; + + sd_write_lock(&lock); + snprintf(path, sizeof(path), "%s%016"PRIx64, lockdir, lock_id); + fd = open(path, O_RDONLY | O_CREAT, sd_def_fmode); + if (fd < 0) + panic("failed to open %s, %m", path); + + if (xflock(fd, LOCK_EX) < 0) + panic("lock file failed %s, %m", path); + close(fd); } static void local_unlock(uint64_t lock_id) { + char path[PATH_MAX]; + int fd; + + snprintf(path, sizeof(path), "%s%016"PRIx64, lockdir, lock_id); + fd = open(path, O_RDONLY, sd_def_fmode); + if (fd < 0) + panic("failed to open %s, %m", path); + + if (xflock(fd, LOCK_UN) < 0) + panic("unlock file failed %s, %m", path); + close(fd); + sd_unlock(&lock); } static int local_update_node(struct sd_node *node) -- 1.7.9.5 -- sheepdog mailing list sheepdog@lists.wpkg.org http://lists.wpkg.org/mailman/listinfo/sheepdog