At Fri, 3 Apr 2015 11:20:48 +0800, Liu Yuan wrote: > > From: Liu Yuan <liuy...@cmss.chinamobile.com> > > This is a prepation patch to make util.c self-contained and then can be used > outside sheep. > > Signed-off-by: Liu Yuan <liuy...@cmss.chinamobile.com> > --- > dog/common.c | 25 +++++ > dog/dog.h | 5 + > include/Makefile.am | 3 +- > include/util.h | 18 ---- > lib/Makefile.am | 3 +- > lib/common.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/logger.c | 1 + > lib/util.c | 282 > ---------------------------------------------------- > sheep/cluster.h | 1 + > sheep/sheep_priv.h | 1 + > sheepfs/core.c | 1 + > shepherd/shepherd.c | 1 + > 12 files changed, 318 insertions(+), 302 deletions(-) > create mode 100644 lib/common.c
This patch cannot be built even without 8th. Error message is: CC logger.o logger.c:39:20: fatal error: common.h: No such file or directory #include "common.h" common.h might be forgotten. Thanks, Hitoshi > > diff --git a/dog/common.c b/dog/common.c > index 6ff1e19..e3cb3a2 100644 > --- a/dog/common.c > +++ b/dog/common.c > @@ -14,6 +14,31 @@ > #include "sockfd_cache.h" > #include "fec.h" > > +struct timespec get_time_tick(void) > +{ > + struct timespec ts; > + int ret; > + > + ts.tv_sec = 0; > + ts.tv_nsec = 0; > + > + ret = clock_gettime(CLOCK_MONOTONIC, &ts); > + if (ret < 0) > + sd_err("clock_gettime failure: %m"); > + > + return ts; > +} > + > +double get_time_interval(const struct timespec *start, > + const struct timespec *end) > +{ > + assert(start); > + assert(end); > + > + return ((end->tv_nsec - start->tv_nsec) * 0.000000001) > + + end->tv_sec - start->tv_sec; > +} > + > char *strnumber_raw(uint64_t _size, bool raw) > { > const char *units[] = {"MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; > diff --git a/dog/dog.h b/dog/dog.h > index bcf0e6e..707f31b 100644 > --- a/dog/dog.h > +++ b/dog/dog.h > @@ -25,6 +25,7 @@ > #include "work.h" > #include "event.h" > #include "config.h" > +#include "common.h" > > #define CMD_NEED_NODELIST (1 << 0) > #define CMD_NEED_ARG (1 << 1) > @@ -105,6 +106,10 @@ int dog_bnode_reader(uint64_t oid, void **mem, unsigned > int len, > int read_vdi_obj(const char *vdiname, int snapid, const char *tag, > uint32_t *pvid, struct sd_inode *inode, size_t size); > > +struct timespec get_time_tick(void); > +double get_time_interval(const struct timespec *start, > + const struct timespec *end); > + > extern struct command vdi_command; > extern struct command node_command; > extern struct command cluster_command; > diff --git a/include/Makefile.am b/include/Makefile.am > index ad73266..6fee5c8 100644 > --- a/include/Makefile.am > +++ b/include/Makefile.am > @@ -3,4 +3,5 @@ MAINTAINERCLEANFILES = Makefile.in config.h.in > noinst_HEADERS = bitops.h event.h logger.h sheepdog_proto.h util.h \ > list.h net.h sheep.h exits.h strbuf.h rbtree.h \ > sha1.h option.h internal_proto.h shepherd.h work.h \ > - sockfd_cache.h compiler.h fec.h lttng_disable.h > + sockfd_cache.h compiler.h fec.h lttng_disable.h \ > + common.h > diff --git a/include/util.h b/include/util.h > index 632a193..6c11b54 100644 > --- a/include/util.h > +++ b/include/util.h > @@ -106,15 +106,8 @@ int eventfd_xread(int efd); > void eventfd_xwrite(int efd, int value); > void pstrcpy(char *buf, int buf_size, const char *str); > char *chomp(char *str); > -int rmdir_r(const char *dir_path); > -int purge_directory(const char *dir_path); > -int purge_directory_async(const char *dir_path); > bool is_numeric(const char *p); > const char *data_to_str(void *data, size_t data_length); > -int install_sighandler(int signum, void (*handler)(int, siginfo_t *, void *), > - bool once); > -int install_crash_handler(void (*handler)(int, siginfo_t *, void *)); > -void reraise_crash_signal(int signo, int status); > pid_t gettid(void); > int tkill(int tid, int sig); > bool is_xattr_enabled(const char *path); > @@ -123,16 +116,9 @@ const char *my_exe_path(void); > int split_path(const char *path, size_t nr_segs, char **segs); > void make_path(char *path, size_t size, size_t nr_segs, const char **segs); > > -int atomic_create_and_write(const char *path, const char *buf, size_t len, > - bool force_create); > - > void find_zero_blocks(const void *buf, uint64_t *poffset, uint32_t *plen); > void trim_zero_blocks(void *buf, uint64_t *poffset, uint32_t *plen); > > -struct timespec get_time_tick(void); > -double get_time_interval(const struct timespec *start, > - const struct timespec *end); > - > /* a type safe version of qsort() */ > #define xqsort(base, nmemb, compar) \ > ({ \ > @@ -562,8 +548,4 @@ static inline uint64_t clock_get_time(void) > } > > char *xstrdup(const char *s); > - > -struct work_queue; > -void register_util_wq(struct work_queue *wq); > - > #endif > diff --git a/lib/Makefile.am b/lib/Makefile.am > index a630977..697c5ba 100644 > --- a/lib/Makefile.am > +++ b/lib/Makefile.am > @@ -13,7 +13,8 @@ libisa_a_SOURCES = $(shell find isa-l/ -type f -regex > ".*\.\(c\|h\|asm\)") \ > isa-l/make.inc > > libsheepdog_a_SOURCES = event.c logger.c net.c util.c rbtree.c > strbuf.c \ > - sha1.c option.c work.c sockfd_cache.c fec.c sd_inode.c > + sha1.c option.c work.c sockfd_cache.c fec.c \ > + sd_inode.c common.c > > libsheepdog_a_LIBADD = isa-l/bin/ec_base.o \ > isa-l/bin/ec_highlevel_func.o \ > diff --git a/lib/common.c b/lib/common.c > new file mode 100644 > index 0000000..52c6ef4 > --- /dev/null > +++ b/lib/common.c > @@ -0,0 +1,279 @@ > +/* > + * Copyright (C) 2015 China Mobile Inc. > + * > + * Liu Yuan <liuy...@cmss.chinamobile.com> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License version > + * 2 as published by the Free Software Foundation. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +/* This file contains shared functionalities for libsheepdog.a */ > + > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <fcntl.h> > +#include <dirent.h> > + > +#include "util.h" > +#include "work.h" > +#include "common.h" > + > +static struct work_queue *util_wqueue; > + > +void register_util_wq(struct work_queue *wq) > +{ > + util_wqueue = wq; > +} > + > +/* > + * If force_create is true, this function create the file even when the > + * temporary file exists. > + */ > +int atomic_create_and_write(const char *path, const char *buf, size_t len, > + bool force_create) > +{ > + int fd, ret; > + char tmp_path[PATH_MAX]; > + > + snprintf(tmp_path, PATH_MAX, "%s.tmp", path); > +again: > + fd = open(tmp_path, O_WRONLY | O_CREAT | O_SYNC | O_EXCL, sd_def_fmode); > + if (fd < 0) { > + if (errno == EEXIST) { > + if (force_create) { > + sd_debug("clean up a temporary file %s", > + tmp_path); > + unlink(tmp_path); > + goto again; > + } else > + sd_debug("someone else is dealing with %s", > + tmp_path); > + } else > + sd_err("failed to open temporal file %s, %m", tmp_path); > + ret = -1; > + goto end; > + } > + > + ret = xwrite(fd, buf, len); > + if (unlikely(ret != len)) { > + sd_err("failed to write %s, %m", path); > + ret = -1; > + goto close_fd; > + } > + > + ret = rename(tmp_path, path); > + if (unlikely(ret < 0)) { > + sd_err("failed to rename %s, %m", path); > + ret = -1; > + } > + > +close_fd: > + close(fd); > +end: > + return ret; > +} > + > +struct purge_work_unit { > + bool is_dir; > + char path[PATH_MAX]; > +}; > + > +struct purge_work { > + struct work work; > + > + int nr_units, units_size; > + struct purge_work_unit *units; > +}; > + > +static void purge_work_fn(struct work *work) > +{ > + struct purge_work *pw = container_of(work, struct purge_work, work); > + int ret; > + > + for (int i = 0 ; i < pw->nr_units; i++) { > + struct purge_work_unit *unit; > + > + unit = &pw->units[i]; > + > + if (unit->is_dir) > + ret = rmdir_r(unit->path); > + else > + ret = unlink(unit->path); > + > + if (ret) > + sd_err("failed to remove %s %s: %m", > + unit->is_dir ? "directory" : "file", unit->path); > + > + /* > + * We cannot check and do something even above rmdir_r() and > + * unlink() cause error. Actually, sd_store->cleanup() (typical > + * user of purge_directory()) call of > + * cluster_recovery_completion() ignores its error code. > + */ > + } > +} > + > +static void purge_work_done(struct work *work) > +{ > + struct purge_work *pw = container_of(work, struct purge_work, work); > + > + sd_debug("purging work done, number of units: %d", pw->nr_units); > + > + free(pw->units); > + free(pw); > +} > + > +/* Purge directory recursively */ > +static int raw_purge_directory(const char *dir_path, bool async) > +{ > + int ret = 0; > + struct stat s; > + DIR *dir; > + struct dirent *d; > + char path[PATH_MAX]; > + struct purge_work *w = NULL; > + > + dir = opendir(dir_path); > + if (!dir) { > + if (errno != ENOENT) > + sd_err("failed to open %s: %m", dir_path); > + return -errno; > + } > + > + if (async && util_wqueue) { > + /* we have workqueue for it, don't unlink in this thread */ > + w = xzalloc(sizeof(*w)); > + w->nr_units = 0; > + w->units_size = 512; /* should this value be configurable? */ > + w->units = xcalloc(w->units_size, sizeof(w->units[0])); > + } > + > + while ((d = readdir(dir))) { > + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) > + continue; > + > + snprintf(path, sizeof(path), "%s/%s", dir_path, d->d_name); > + ret = stat(path, &s); > + if (ret) { > + sd_err("failed to stat %s: %m", path); > + goto out; > + } > + > + if (async && util_wqueue) { > + struct purge_work_unit *unit; > + > + unit = &w->units[w->nr_units++]; > + > + unit->is_dir = S_ISDIR(s.st_mode); > + pstrcpy(unit->path, PATH_MAX, path); > + > + if (w->nr_units == w->units_size) { > + w->units_size *= 2; > + w->units = xrealloc(w->units, > + sizeof(struct purge_work_unit) * > + w->units_size); > + } > + } else { > + if (S_ISDIR(s.st_mode)) > + ret = rmdir_r(path); > + else > + ret = unlink(path); > + > + if (ret != 0) { > + sd_err("failed to remove %s %s: %m", > + S_ISDIR(s.st_mode) ? > + "directory" : "file", > + path); > + goto out; > + } > + } > + } > + > + if (async && util_wqueue) { > + w->work.fn = purge_work_fn; > + w->work.done = purge_work_done; > + queue_work(util_wqueue, &w->work); > + } > + > +out: > + closedir(dir); > + return ret; > +} > + > +int purge_directory(const char *dir_path) > +{ > + return raw_purge_directory(dir_path, false); > +} > + > +int purge_directory_async(const char *dir_path) > +{ > + return raw_purge_directory(dir_path, true); > +} > + > +/* remove directory recursively */ > +int rmdir_r(const char *dir_path) > +{ > + int ret; > + > + ret = purge_directory(dir_path); > + if (ret == 0) > + ret = rmdir(dir_path); > + > + return ret; > +} > + > +/* > + * If 'once' is true, the signal will be restored to the default state > + * after 'handler' is called. > + */ > +int install_sighandler(int signum, void (*handler)(int, siginfo_t *, void *), > + bool once) > +{ > + struct sigaction sa = {}; > + > + sa.sa_sigaction = handler; > + sa.sa_flags = SA_SIGINFO; > + > + if (once) > + sa.sa_flags = sa.sa_flags | SA_RESETHAND | SA_NODEFER; > + sigemptyset(&sa.sa_mask); > + > + return sigaction(signum, &sa, NULL); > +} > + > +int install_crash_handler(void (*handler)(int, siginfo_t *, void *)) > +{ > + return install_sighandler(SIGSEGV, handler, true) || > + install_sighandler(SIGABRT, handler, true) || > + install_sighandler(SIGBUS, handler, true) || > + install_sighandler(SIGILL, handler, true) || > + install_sighandler(SIGFPE, handler, true) || > + install_sighandler(SIGQUIT, handler, true); > +} > + > +/* > + * Re-raise the signal 'signo' for the default signal handler to dump > + * a core file, and exit with 'status' if the default handler cannot > + * terminate the process. This function is expected to be called in > + * the installed signal handlers with install_crash_handler(). > + */ > +void reraise_crash_signal(int signo, int status) > +{ > + int ret = raise(signo); > + > + /* We won't get here normally. */ > + if (ret != 0) > + sd_emerg("failed to re-raise signal %d (%s).", > + signo, strsignal(signo)); > + else > + sd_emerg("default handler for the re-raised " > + "signal %d (%s) didn't work as expected", signo, > + strsignal(signo)); > + > + exit(status); > +} > + > diff --git a/lib/logger.c b/lib/logger.c > index 39d3283..ffe84fc 100644 > --- a/lib/logger.c > +++ b/lib/logger.c > @@ -36,6 +36,7 @@ > #include <linux/limits.h> > > #include "util.h" > +#include "common.h" > > static bool colorize; > static const char * const log_color[] = { > diff --git a/lib/util.c b/lib/util.c > index aad6d96..af9747a 100644 > --- a/lib/util.c > +++ b/lib/util.c > @@ -21,14 +21,6 @@ > #include <fcntl.h> > > #include "util.h" > -#include "work.h" > - > -static struct work_queue *util_wqueue; > - > -void register_util_wq(struct work_queue *wq) > -{ > - util_wqueue = wq; > -} > > mode_t sd_def_dmode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | > S_IXGRP; > mode_t sd_def_fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; > @@ -117,7 +109,6 @@ int prealloc(int fd, uint32_t size) > int ret = xfallocate(fd, 0, 0, size); > if (ret < 0) { > if (errno != ENOSYS && errno != EOPNOTSUPP) { > - sd_err("failed to preallocate space, %m"); > return ret; > } > > @@ -366,155 +357,6 @@ char *chomp(char *str) > return str; > } > > -struct purge_work_unit { > - bool is_dir; > - char path[PATH_MAX]; > -}; > - > -struct purge_work { > - struct work work; > - > - int nr_units, units_size; > - struct purge_work_unit *units; > -}; > - > -static void purge_work_fn(struct work *work) > -{ > - struct purge_work *pw = container_of(work, struct purge_work, work); > - int ret; > - > - for (int i = 0 ; i < pw->nr_units; i++) { > - struct purge_work_unit *unit; > - > - unit = &pw->units[i]; > - > - if (unit->is_dir) > - ret = rmdir_r(unit->path); > - else > - ret = unlink(unit->path); > - > - if (ret) > - sd_err("failed to remove %s %s: %m", > - unit->is_dir ? "directory" : "file", unit->path); > - > - /* > - * We cannot check and do something even above rmdir_r() and > - * unlink() cause error. Actually, sd_store->cleanup() (typical > - * user of purge_directory()) call of > - * cluster_recovery_completion() ignores its error code. > - */ > - } > -} > - > -static void purge_work_done(struct work *work) > -{ > - struct purge_work *pw = container_of(work, struct purge_work, work); > - > - sd_debug("purging work done, number of units: %d", pw->nr_units); > - > - free(pw->units); > - free(pw); > -} > - > -/* Purge directory recursively */ > -static int raw_purge_directory(const char *dir_path, bool async) > -{ > - int ret = 0; > - struct stat s; > - DIR *dir; > - struct dirent *d; > - char path[PATH_MAX]; > - struct purge_work *w = NULL; > - > - dir = opendir(dir_path); > - if (!dir) { > - if (errno != ENOENT) > - sd_err("failed to open %s: %m", dir_path); > - return -errno; > - } > - > - if (async && util_wqueue) { > - /* we have workqueue for it, don't unlink in this thread */ > - w = xzalloc(sizeof(*w)); > - w->nr_units = 0; > - w->units_size = 512; /* should this value be configurable? */ > - w->units = xcalloc(w->units_size, sizeof(w->units[0])); > - } > - > - while ((d = readdir(dir))) { > - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) > - continue; > - > - snprintf(path, sizeof(path), "%s/%s", dir_path, d->d_name); > - ret = stat(path, &s); > - if (ret) { > - sd_err("failed to stat %s: %m", path); > - goto out; > - } > - > - if (async && util_wqueue) { > - struct purge_work_unit *unit; > - > - unit = &w->units[w->nr_units++]; > - > - unit->is_dir = S_ISDIR(s.st_mode); > - strcpy(unit->path, path); > - > - if (w->nr_units == w->units_size) { > - w->units_size *= 2; > - w->units = xrealloc(w->units, > - sizeof(struct purge_work_unit) * > - w->units_size); > - } > - } else { > - if (S_ISDIR(s.st_mode)) > - ret = rmdir_r(path); > - else > - ret = unlink(path); > - > - if (ret != 0) { > - sd_err("failed to remove %s %s: %m", > - S_ISDIR(s.st_mode) ? > - "directory" : "file", > - path); > - goto out; > - } > - } > - } > - > - if (async && util_wqueue) { > - w->work.fn = purge_work_fn; > - w->work.done = purge_work_done; > - queue_work(util_wqueue, &w->work); > - } > - > -out: > - closedir(dir); > - return ret; > -} > - > -int purge_directory(const char *dir_path) > -{ > - return raw_purge_directory(dir_path, false); > -} > - > -int purge_directory_async(const char *dir_path) > -{ > - return raw_purge_directory(dir_path, true); > -} > - > -/* remove directory recursively */ > -int rmdir_r(const char *dir_path) > -{ > - int ret; > - > - ret = purge_directory(dir_path); > - if (ret == 0) > - ret = rmdir(dir_path); > - > - return ret; > -} > - > bool is_numeric(const char *s) > { > const char *p = s; > @@ -546,57 +388,6 @@ const char *data_to_str(void *data, size_t data_length) > return "(not string)"; > } > > -/* > - * If 'once' is true, the signal will be restored to the default state > - * after 'handler' is called. > - */ > -int install_sighandler(int signum, void (*handler)(int, siginfo_t *, void *), > - bool once) > -{ > - struct sigaction sa = {}; > - > - sa.sa_sigaction = handler; > - sa.sa_flags = SA_SIGINFO; > - > - if (once) > - sa.sa_flags = sa.sa_flags | SA_RESETHAND | SA_NODEFER; > - sigemptyset(&sa.sa_mask); > - > - return sigaction(signum, &sa, NULL); > -} > - > -int install_crash_handler(void (*handler)(int, siginfo_t *, void *)) > -{ > - return install_sighandler(SIGSEGV, handler, true) || > - install_sighandler(SIGABRT, handler, true) || > - install_sighandler(SIGBUS, handler, true) || > - install_sighandler(SIGILL, handler, true) || > - install_sighandler(SIGFPE, handler, true) || > - install_sighandler(SIGQUIT, handler, true); > -} > - > -/* > - * Re-raise the signal 'signo' for the default signal handler to dump > - * a core file, and exit with 'status' if the default handler cannot > - * terminate the process. This function is expected to be called in > - * the installed signal handlers with install_crash_handler(). > - */ > -void reraise_crash_signal(int signo, int status) > -{ > - int ret = raise(signo); > - > - /* We won't get here normally. */ > - if (ret != 0) > - sd_emerg("failed to re-raise signal %d (%s).", > - signo, strsignal(signo)); > - else > - sd_emerg("default handler for the re-raised " > - "signal %d (%s) didn't work as expected", signo, > - strsignal(signo)); > - > - exit(status); > -} > - > pid_t gettid(void) > { > return syscall(SYS_gettid); > @@ -684,54 +475,6 @@ void make_path(char *path, size_t size, size_t nr_segs, > const char **segs) > } > > /* > - * If force_create is true, this function create the file even when the > - * temporary file exists. > - */ > -int atomic_create_and_write(const char *path, const char *buf, size_t len, > - bool force_create) > -{ > - int fd, ret; > - char tmp_path[PATH_MAX]; > - > - snprintf(tmp_path, PATH_MAX, "%s.tmp", path); > -again: > - fd = open(tmp_path, O_WRONLY | O_CREAT | O_SYNC | O_EXCL, sd_def_fmode); > - if (fd < 0) { > - if (errno == EEXIST) { > - if (force_create) { > - sd_debug("clean up a temporary file %s", > - tmp_path); > - unlink(tmp_path); > - goto again; > - } else > - sd_debug("someone else is dealing with %s", > - tmp_path); > - } else > - sd_err("failed to open temporal file %s, %m", tmp_path); > - ret = -1; > - goto end; > - } > - > - ret = xwrite(fd, buf, len); > - if (unlikely(ret != len)) { > - sd_err("failed to write %s, %m", path); > - ret = -1; > - goto close_fd; > - } > - > - ret = rename(tmp_path, path); > - if (unlikely(ret < 0)) { > - sd_err("failed to rename %s, %m", path); > - ret = -1; > - } > - > -close_fd: > - close(fd); > -end: > - return ret; > -} > - > -/* > * Returns a list organized in an intermediate format suited > * to chaining of merge() calls: null-terminated, no reserved or > * sentinel head node, "prev" links not maintained. > @@ -930,31 +673,6 @@ void trim_zero_blocks(void *buf, uint64_t *poffset, > uint32_t *plen) > memmove(p, p + *poffset - orig_offset, *plen); > } > > -struct timespec get_time_tick(void) > -{ > - struct timespec ts; > - int ret; > - > - ts.tv_sec = 0; > - ts.tv_nsec = 0; > - > - ret = clock_gettime(CLOCK_MONOTONIC, &ts); > - if (ret < 0) > - sd_err("clock_gettime failure: %m"); > - > - return ts; > -} > - > -double get_time_interval(const struct timespec *start, > - const struct timespec *end) > -{ > - assert(start); > - assert(end); > - > - return ((end->tv_nsec - start->tv_nsec) * 0.000000001) > - + end->tv_sec - start->tv_sec; > -} > - > char *xstrdup(const char *s) > { > char *ret; > diff --git a/sheep/cluster.h b/sheep/cluster.h > index cc111e2..e70c8b6 100644 > --- a/sheep/cluster.h > +++ b/sheep/cluster.h > @@ -22,6 +22,7 @@ > #include "sheepdog_proto.h" > #include "sheep.h" > #include "config.h" > +#include "common.h" > > /* > * maximum payload size sent in ->notify and ->unblock, it should be large > diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h > index 26afa89..3876b31 100644 > --- a/sheep/sheep_priv.h > +++ b/sheep/sheep_priv.h > @@ -43,6 +43,7 @@ > #include "config.h" > #include "sockfd_cache.h" > #include "fec.h" > +#include "common.h" > > /* > * Functions that update global info must be called in the main > diff --git a/sheepfs/core.c b/sheepfs/core.c > index 1bcbaec..473cbb5 100644 > --- a/sheepfs/core.c > +++ b/sheepfs/core.c > @@ -26,6 +26,7 @@ > #include "util.h" > #include "sheepfs.h" > #include "sheepdog_proto.h" > +#include "common.h" > > #define SH_OP_NAME "user.sheepfs.opcode" > #define SH_OP_SIZE sizeof(uint32_t) > diff --git a/shepherd/shepherd.c b/shepherd/shepherd.c > index dc6df74..19c217c 100644 > --- a/shepherd/shepherd.c > +++ b/shepherd/shepherd.c > @@ -33,6 +33,7 @@ > #include "util.h" > #include "option.h" > #include "shepherd.h" > +#include "common.h" > > #define EPOLL_SIZE SD_MAX_NODES > > -- > 1.9.1 > > -- > sheepdog mailing list > sheepdog@lists.wpkg.org > https://lists.wpkg.org/mailman/listinfo/sheepdog -- sheepdog mailing list sheepdog@lists.wpkg.org https://lists.wpkg.org/mailman/listinfo/sheepdog