summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2007-02-01 12:36:21 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:17:38 -0500
commit8b7233f19b4e294bf4174439b3acc427552dc4ee (patch)
tree1f7add10d1ddc86648d9e03b06bb2a9228c3cc55
parentf2b8db93c4e6aba0b48453619069bc54af45f353 (diff)
downloadsamba-8b7233f19b4e294bf4174439b3acc427552dc4ee.tar.gz
samba-8b7233f19b4e294bf4174439b3acc427552dc4ee.tar.bz2
samba-8b7233f19b4e294bf4174439b3acc427552dc4ee.zip
r21107: Adapt notify_fam.c to the new infrastructure. This works in my test, but does
not survive the raw-notify test just because famd is too slow. Events are coming in too late and are thus unsyncronized. Now to get that through the VFS. Volker (This used to be commit c84bf6c4f92ffe3728acef7de7cefbc08307ea39)
-rw-r--r--source3/smbd/notify_fam.c166
1 files changed, 90 insertions, 76 deletions
diff --git a/source3/smbd/notify_fam.c b/source3/smbd/notify_fam.c
index 89bbddae24..3fa6dad162 100644
--- a/source3/smbd/notify_fam.c
+++ b/source3/smbd/notify_fam.c
@@ -21,7 +21,7 @@
#include "includes.h"
-#if 0
+#ifdef HAVE_FAM_CHANGE_NOTIFY
#include <fam.h>
@@ -44,23 +44,30 @@ typedef enum FAMCodes FAMCodes;
* http://sourceforge.net/projects/bsdfam/
*/
-static void *fam_notify_add(TALLOC_CTX *mem_ctx,
- struct event_context *event_ctx,
- files_struct *fsp, uint32 *filter);
-
/* ------------------------------------------------------------------------- */
-struct fam_notify_ctx {
- struct fam_notify_ctx *prev, *next;
+struct fam_watch_context {
+ struct fam_watch_context *prev, *next;
FAMConnection *fam_connection;
struct FAMRequest fr;
- files_struct *fsp;
- char *path;
- uint32 filter;
+ struct sys_notify_context *sys_ctx;
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev);
+ void *private_data;
+ uint32_t mask; /* the inotify mask */
+ uint32_t filter; /* the windows completion filter */
+ const char *path;
};
-static struct fam_notify_ctx *fam_notify_list;
+
+/*
+ * We want one FAM connection per smbd, not one per tcon.
+ */
static FAMConnection fam_connection;
+static BOOL fam_connection_initialized = False;
+
+static struct fam_watch_context *fam_notify_list;
static void fam_handler(struct event_context *event_ctx,
struct fd_event *fd_event,
uint16 flags,
@@ -84,7 +91,7 @@ static NTSTATUS fam_open_connection(FAMConnection *fam_conn,
SAFE_FREE(name);
if (res < 0) {
- DEBUG(5, ("FAM file change notifications not available\n"));
+ DEBUG(10, ("FAM file change notifications not available\n"));
/*
* No idea how to get NT_STATUS from a FAM result
*/
@@ -107,9 +114,9 @@ static NTSTATUS fam_open_connection(FAMConnection *fam_conn,
static void fam_reopen(FAMConnection *fam_conn,
struct event_context *event_ctx,
- struct fam_notify_ctx *notify_list)
+ struct fam_watch_context *notify_list)
{
- struct fam_notify_ctx *ctx;
+ struct fam_watch_context *ctx;
DEBUG(5, ("Re-opening FAM connection\n"));
@@ -132,8 +139,8 @@ static void fam_handler(struct event_context *event_ctx,
{
FAMConnection *fam_conn = (FAMConnection *)private_data;
FAMEvent fam_event;
- struct fam_notify_ctx *ctx;
- char *name;
+ struct fam_watch_context *ctx;
+ struct notify_event ne;
if (FAMPending(fam_conn) == 0) {
DEBUG(10, ("fam_handler called but nothing pending\n"));
@@ -141,13 +148,23 @@ static void fam_handler(struct event_context *event_ctx,
}
if (FAMNextEvent(fam_conn, &fam_event) != 1) {
- DEBUG(10, ("FAMNextEvent returned an error\n"));
+ DEBUG(5, ("FAMNextEvent returned an error\n"));
TALLOC_FREE(fd_event);
fam_reopen(fam_conn, event_ctx, fam_notify_list);
return;
}
- if ((fam_event.code != FAMCreated) && (fam_event.code != FAMDeleted)) {
+ DEBUG(10, ("Got FAMCode %d for %s\n", fam_event.code,
+ fam_event.filename));
+
+ switch (fam_event.code) {
+ case FAMCreated:
+ ne.action = NOTIFY_ACTION_ADDED;
+ break;
+ case FAMDeleted:
+ ne.action = NOTIFY_ACTION_REMOVED;
+ break;
+ default:
DEBUG(10, ("Ignoring code FAMCode %d for file %s\n",
(int)fam_event.code, fam_event.filename));
return;
@@ -165,17 +182,14 @@ static void fam_handler(struct event_context *event_ctx,
return;
}
- if ((name = strrchr_m(fam_event.filename, '\\')) == NULL) {
- name = fam_event.filename;
+ if ((ne.path = strrchr_m(fam_event.filename, '\\')) == NULL) {
+ ne.path = fam_event.filename;
}
- notify_fsp(ctx->fsp,
- fam_event.code == FAMCreated
- ? NOTIFY_ACTION_ADDED : NOTIFY_ACTION_REMOVED,
- name);
+ ctx->callback(ctx->sys_ctx, ctx->private_data, &ne);
}
-static int fam_notify_ctx_destructor(struct fam_notify_ctx *ctx)
+static int fam_watch_context_destructor(struct fam_watch_context *ctx)
{
if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) {
FAMCancelMonitor(&fam_connection, &ctx->fr);
@@ -184,86 +198,86 @@ static int fam_notify_ctx_destructor(struct fam_notify_ctx *ctx)
return 0;
}
-static void *fam_notify_add(TALLOC_CTX *mem_ctx,
- struct event_context *event_ctx,
- files_struct *fsp, uint32 *filter)
+/*
+ add a watch. The watch is removed when the caller calls
+ talloc_free() on *handle
+*/
+NTSTATUS fam_watch(struct sys_notify_context *ctx,
+ struct notify_entry *e,
+ void (*callback)(struct sys_notify_context *ctx,
+ void *private_data,
+ struct notify_event *ev),
+ void *private_data,
+ void *handle_p)
{
- struct fam_notify_ctx *ctx;
-
- if ((*filter & FILE_NOTIFY_CHANGE_FILE_NAME) == 0) {
- DEBUG(10, ("filter = %u, no FILE_NOTIFY_CHANGE_FILE_NAME\n",
- *filter));
- return NULL;
+ const uint32 fam_mask = (FILE_NOTIFY_CHANGE_FILE_NAME|
+ FILE_NOTIFY_CHANGE_DIR_NAME);
+ struct fam_watch_context *watch;
+ void **handle = (void **)handle_p;
+
+ if ((e->filter & fam_mask) == 0) {
+ DEBUG(10, ("filter = %u, ignoring in FAM\n", e->filter));
+ return NT_STATUS_OK;
}
- if (!(ctx = TALLOC_P(mem_ctx, struct fam_notify_ctx))) {
- return NULL;
+ if (!fam_connection_initialized) {
+ if (!NT_STATUS_IS_OK(fam_open_connection(&fam_connection,
+ ctx->ev))) {
+ /*
+ * Just let smbd do all the work itself
+ */
+ return NT_STATUS_OK;
+ }
+ fam_connection_initialized = True;
}
- ctx->fsp = fsp;
- ctx->fam_connection = &fam_connection;
+ if (!(watch = TALLOC_P(ctx, struct fam_watch_context))) {
+ return NT_STATUS_NO_MEMORY;
+ }
- /*
- * The FAM module in this early state will only take care of
- * FAMCreated and FAMDeleted events
- */
+ watch->fam_connection = &fam_connection;
- ctx->filter = FILE_NOTIFY_CHANGE_FILE_NAME;
+ watch->callback = callback;
+ watch->private_data = private_data;
+ watch->sys_ctx = ctx;
- if (!(ctx->path = talloc_asprintf(ctx, "%s/%s", fsp->conn->connectpath,
- fsp->fsp_name))) {
+ if (!(watch->path = talloc_strdup(watch, e->path))) {
DEBUG(0, ("talloc_asprintf failed\n"));
- TALLOC_FREE(ctx);
- return NULL;
+ TALLOC_FREE(watch);
+ return NT_STATUS_NO_MEMORY;
}
/*
- * Leave the rest to smbd itself
+ * The FAM module in this early state will only take care of
+ * FAMCreated and FAMDeleted events, Leave the rest to
+ * notify_internal.c
*/
- *filter &= ~FILE_NOTIFY_CHANGE_FILE_NAME;
+ watch->filter = fam_mask;
+ e->filter &= ~fam_mask;
- DLIST_ADD(fam_notify_list, ctx);
- talloc_set_destructor(ctx, fam_notify_ctx_destructor);
+ DLIST_ADD(fam_notify_list, watch);
+ talloc_set_destructor(watch, fam_watch_context_destructor);
/*
* Only directories monitored so far
*/
- if (FAMCONNECTION_GETFD(ctx->fam_connection) != -1) {
- FAMMonitorDirectory(ctx->fam_connection, ctx->path, &ctx->fr,
- NULL);
+ if (FAMCONNECTION_GETFD(watch->fam_connection) != -1) {
+ FAMMonitorDirectory(watch->fam_connection, watch->path,
+ &watch->fr, NULL);
}
else {
/*
* If the re-open is successful, this will establish the
* FAMMonitor from the list
*/
- fam_reopen(ctx->fam_connection, event_ctx, fam_notify_list);
+ fam_reopen(watch->fam_connection, ctx->ev, fam_notify_list);
}
- return ctx;
-}
-
-static struct cnotify_fns global_fam_notify =
-{
- fam_notify_add,
-};
+ *handle = (void *)watch;
-struct cnotify_fns *fam_notify_init(struct event_context *event_ctx)
-{
-
- ZERO_STRUCT(fam_connection);
- FAMCONNECTION_GETFD(&fam_connection) = -1;
-
- if (!NT_STATUS_IS_OK(fam_open_connection(&fam_connection,
- event_ctx))) {
- DEBUG(0, ("FAM file change notifications not available\n"));
- return NULL;
- }
-
- DEBUG(10, ("enabling FAM change notifications\n"));
- return &global_fam_notify;
+ return NT_STATUS_OK;
}
#endif /* HAVE_FAM_CHANGE_NOTIFY */