redmine

Added untested kqueue fix for pipes and symlinks

... ... @@ -5,10 +5,10 @@ if CLSYNC
bin_PROGRAMS = clsync
clsync_SOURCES = calc.c cluster.c error.c fileutils.c glibex.c \
indexes.c main.c malloc.c rules.c stringex.c sync.c privileged.c\
pthreadex.c calc.h cluster.h fileutils.h glibex.h main.h \
port-hacks.h pthreadex.h stringex.h sync.h common.h control.h \
privileged.h rules.h syscalls.h
indexes.c main.c malloc.c rules.c searchex.c stringex.c sync.c \
privileged.c pthreadex.c calc.h cluster.h fileutils.h glibex.h \
main.h port-hacks.h pthreadex.h searchex.h stringex.h sync.h \
common.h control.h privileged.h rules.h syscalls.h
clsync_CFLAGS = $(AM_CFLAGS)
... ...
... ... @@ -26,6 +26,7 @@
#include "indexes.h"
#include "fileutils.h"
#include "calc.h"
#include "searchex.h"
#include "mon_kqueue.h"
struct monobj {
... ... @@ -38,6 +39,10 @@ struct monobj {
uint32_t name_hash;
unsigned char type;
size_t changelist_id;
struct monobj *parent;
// For directories only
void *children_tree;
};
typedef struct monobj monobj_t;
... ... @@ -50,7 +55,7 @@ struct kqueue_data {
struct kevent eventlist[KQUEUE_EVENTLISTSIZE];
size_t eventlist_count;
void *file_btree;
void *fd_btree;
void *fd_btree;
};
struct recognize_event_return {
... ... @@ -185,6 +190,7 @@ int kqueue_mark(ctx_t *ctx_p, monobj_t *obj_p) {
return 0;
}
int kqueue_unmark(ctx_t *ctx_p, monobj_t *obj_p) {
struct kqueue_data *dat = ctx_p->fsmondata;
#ifdef VERYPARANOID
... ... @@ -201,8 +207,12 @@ int kqueue_unmark(ctx_t *ctx_p, monobj_t *obj_p) {
close(obj_p->fd);
void child_free(monobj_t *node) {
critical_on (kqueue_unmark(ctx_p, node));
}
tdestroy(obj_p->children_tree, (void (*)(void *))child_free);
tdelete(obj_p, &dat->file_btree, monobj_filecmp);
tdelete(obj_p, &dat->fd_btree, monobj_fdcmp);
tdelete(obj_p, &dat->fd_btree, monobj_fdcmp);
free(obj_p->name);
free(obj_p);
... ... @@ -210,7 +220,7 @@ int kqueue_unmark(ctx_t *ctx_p, monobj_t *obj_p) {
}
monobj_t *kqueue_start_watch(ctx_t *ctx_p, ino_t inode, dev_t device, int dir_fd, const char *const fname, size_t name_len, unsigned char type) {
monobj_t *obj_p;
monobj_t *obj_p, *parent, parent_pattern;
struct kqueue_data *dat = ctx_p->fsmondata;
debug(3, "(ctx_p, %i, \"%s\", %u, %u)", dir_fd, fname, name_len, type);
... ... @@ -224,19 +234,37 @@ monobj_t *kqueue_start_watch(ctx_t *ctx_p, ino_t inode, dev_t device, int dir_fd
memcpy(obj_p->name, fname, obj_p->name_len+1);
obj_p->name_hash = adler32_calc((const unsigned char *)fname, name_len);
if (kqueue_mark(ctx_p, obj_p)) {
error("Got error while kqueue_mark()");
free(obj_p->name);
free(obj_p);
return NULL;
parent_pattern.fd = dir_fd;
obj_p->parent = tfind(&parent_pattern, &dat->fd_btree, monobj_fdcmp);
parent = obj_p->parent;
switch (type) {
case DT_DIR:
case DT_UNKNOWN:
case DT_REG:
if (kqueue_mark(ctx_p, obj_p)) {
error("Got error while kqueue_mark()");
free(obj_p->name);
free(obj_p);
return NULL;
}
break;
default:
debug(4, "I won't open() this object due to it's type == %u.", type);
break;
}
debug(8, "storing: inode == %u; device == %u; dir_fd == %i; fd == %i", obj_p->inode, obj_p->device, obj_p->dir_fd, obj_p->fd);
debug(8, "storing: inode == %u; device == %u; dir_fd == %i; fd == %i; parent == %p", obj_p->inode, obj_p->device, obj_p->dir_fd, obj_p->fd, parent);
if (tsearch((void *)obj_p, &dat->file_btree, monobj_filecmp) == NULL)
critical("Not enough memory");
if (tsearch((void *)obj_p, &dat->fd_btree, monobj_fdcmp) == NULL)
critical("Not enough memory");
if (parent != NULL) {
if (tsearch((void *)obj_p, &parent->children_tree, monobj_filecmp) == NULL)
critical("Not enough memory");
}
return obj_p;
}
... ... @@ -492,7 +520,7 @@ int kqueue_sync(ctx_t *ctx_p, indexes_t *indexes_p, struct kevent *ev_p, monobj_
return 0;
}
static inline int _kqueue_handle_oneevent_dircontent_item(struct kqueue_data *dat, ctx_t *ctx_p, indexes_t *indexes_p, monobj_t *dir_obj_p, struct dirent *entry) {
static inline int _kqueue_handle_oneevent_dircontent_item(struct kqueue_data *dat, ctx_t *ctx_p, indexes_t *indexes_p, monobj_t *dir_obj_p, struct dirent *entry, void *children_notfound) {
static monobj_t obj, *obj_p;
struct kevent ev = {0};
debug(9, "\"%s\"", entry->d_name);
... ... @@ -508,6 +536,8 @@ static inline int _kqueue_handle_oneevent_dircontent_item(struct kqueue_data *da
if (tfind((void *)&obj, &dat->file_btree, monobj_filecmp) != NULL)
return 0;
tdelete((void *)&obj, &children_notfound, monobj_filecmp);
if ((obj_p = kqueue_start_watch(ctx_p, entry->d_ino, dir_obj_p->device, dir_obj_p->fd, obj.name, obj.name_len, obj.type)) == NULL) {
error("Got error while kqueue_start_watch()");
return -1;
... ... @@ -523,12 +553,16 @@ static inline int _kqueue_handle_oneevent_dircontent_item(struct kqueue_data *da
return 0;
}
static inline int _kqueue_handle_oneevent_dircontent(ctx_t *ctx_p, indexes_t *indexes_p, monobj_t *obj_p) {
int _kqueue_handle_oneevent_dircontent(ctx_t *ctx_p, indexes_t *indexes_p, monobj_t *obj_p) {
DIR *dir;
void *children_tree_dup;
struct dirent *entry;
struct kqueue_data *dat = ctx_p->fsmondata;
debug(8, "obj_p->dir_fd == %i", obj_p->dir_fd);
children_tree_dup = NULL;
tdup(&children_tree_dup, obj_p->children_tree, monobj_filecmp);
int fd;
if (obj_p->dir_fd == -1)
... ... @@ -544,12 +578,24 @@ static inline int _kqueue_handle_oneevent_dircontent(ctx_t *ctx_p, indexes_t *in
continue;
if (!memcmp(entry->d_name, "..", 3))
continue;
if (_kqueue_handle_oneevent_dircontent_item(dat, ctx_p, indexes_p, obj_p, entry)) {
if (_kqueue_handle_oneevent_dircontent_item(dat, ctx_p, indexes_p, obj_p, entry, children_tree_dup)) {
error("Got error while _kqueue_handle_oneevent_dircontent_item(ctx_p, obj_p, entry {->d_name == \"%s\"})", entry->d_name);
return -1;
}
}
void unmarkchild(monobj_t *obj_p) {
static struct kevent ev = {0};
ev.ident = obj_p->fd;
ev.fflags = NOTE_DELETE;
critical_on (kqueue_sync(ctx_p, indexes_p, &ev, obj_p));
debug(4, "Unmarking the child \"%s\" (dir_fd: %i; fd: %i)", obj_p->name, obj_p->dir_fd, obj_p->fd);
kqueue_unmark(ctx_p, obj_p);
return;
}
tdestroy(children_tree_dup, (void (*)(void *))unmarkchild);
closedir(dir);
return 0;
... ... @@ -647,6 +693,9 @@ int kqueue_deinit(ctx_t *ctx_p) {
}
twalk(dat->fd_btree, btree_close);
#endif
// TODO: fix segfault on cleanup:
#if 0
#if __USE_GNU
tdestroy(dat->file_btree, btree_free);
tdestroy(dat->fd_btree, NULL);
... ... @@ -658,6 +707,7 @@ int kqueue_deinit(ctx_t *ctx_p) {
#ifdef PARANOID
ctx_p->fsmondata = NULL;
#endif
#endif
return 0;
}
... ...
/*
clsync - file tree sync utility based on inotify/kqueue/bsm
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"
#include "error.h"
#include <search.h>
int tdup(void **to, void *from, int (*compar)(const void *, const void *)) {
int count;
count =0;
void tdup_item(const void *node_p, const VISIT which, const int depth) {
switch (which) {
case leaf:
tsearch(node_p, to, compar);
count++;
break;
default:
critical("This code shoudn't be reached (%p, %i, %i).", node_p, which, depth);
}
}
twalk(from, tdup_item);
return count;
}
... ...
/*
clsync - file tree sync utility based on inotify/kqueue/bsm
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int tdup(void **to, void *from, int (*compar)(const void *, const void *));
... ...
... ... @@ -3858,8 +3858,7 @@ int sync_run(ctx_t *ctx_p) {
thread_cleanup(ctx_p);
// Closing rest sockets and files
debug(2, "Deinitializing the FS monitor subsystem");
switch (ctx_p->flags[MONITOR]) {
#ifdef INOTIFY_SUPPORT
case NE_INOTIFY:
... ...