summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-03-29 13:31:30 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:59:18 -0500
commit57bde8631fc65f9b8e10eee7f948e5690412bead (patch)
tree73b7545405cf4c70a8de5bc15f1dfd0876a6d15d
parenta339d748ebfdeb1d39b4611c5e8e179f16bbc004 (diff)
downloadsamba-57bde8631fc65f9b8e10eee7f948e5690412bead.tar.gz
samba-57bde8631fc65f9b8e10eee7f948e5690412bead.tar.bz2
samba-57bde8631fc65f9b8e10eee7f948e5690412bead.zip
r14755: the change notify code now passes most of the RAW-NOTIFY test. Still
more work to do though (This used to be commit 4d234b37e528137b5c00f6bbb84c2d6939fea324)
-rw-r--r--source4/ntvfs/common/notify.c7
-rw-r--r--source4/ntvfs/posix/pvfs_mkdir.c6
-rw-r--r--source4/ntvfs/posix/pvfs_notify.c89
-rw-r--r--source4/ntvfs/posix/pvfs_wait.c17
4 files changed, 98 insertions, 21 deletions
diff --git a/source4/ntvfs/common/notify.c b/source4/ntvfs/common/notify.c
index 604b6a1a2d..bc04c830f1 100644
--- a/source4/ntvfs/common/notify.c
+++ b/source4/ntvfs/common/notify.c
@@ -332,9 +332,6 @@ static BOOL notify_match(struct notify_context *notify, struct notify_entry *e,
return False;
}
- if (path[len] == 0) {
- return True;
- }
if (path[len] != '/') {
return False;
}
@@ -395,7 +392,9 @@ void notify_trigger(struct notify_context *notify,
/* this needs to be changed to a log(n) search */
for (i=0;i<notify->array->num_entries;i++) {
if (notify_match(notify, &notify->array->entries[i], path, action)) {
- notify_send(notify, &notify->array->entries[i], path, action);
+ notify_send(notify, &notify->array->entries[i],
+ path + strlen(notify->array->entries[i].path) + 1,
+ action);
}
}
}
diff --git a/source4/ntvfs/posix/pvfs_mkdir.c b/source4/ntvfs/posix/pvfs_mkdir.c
index 047b6f45a7..5ec7df3b9d 100644
--- a/source4/ntvfs/posix/pvfs_mkdir.c
+++ b/source4/ntvfs/posix/pvfs_mkdir.c
@@ -83,6 +83,8 @@ static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
return status;
}
+ notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, name->full_name);
+
return NT_STATUS_OK;
}
@@ -135,6 +137,8 @@ NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
return status;
}
+ notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, name->full_name);
+
return NT_STATUS_OK;
}
@@ -172,5 +176,7 @@ NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs,
return pvfs_map_errno(pvfs, errno);
}
+ notify_trigger(pvfs->notify_context, NOTIFY_ACTION_REMOVED, name->full_name);
+
return NT_STATUS_OK;
}
diff --git a/source4/ntvfs/posix/pvfs_notify.c b/source4/ntvfs/posix/pvfs_notify.c
index 566b6bc0e2..55a9767863 100644
--- a/source4/ntvfs/posix/pvfs_notify.c
+++ b/source4/ntvfs/posix/pvfs_notify.c
@@ -33,10 +33,13 @@ struct pvfs_notify_buffer {
struct notify_changes *changes;
uint32_t max_buffer_size;
uint32_t current_buffer_size;
- void *wait_handle;
+
+ /* these last two are only present when a notify request is
+ pending */
+ struct ntvfs_request *req;
+ struct smb_notify *info;
};
-
/*
destroy a notify buffer. Called when the handle is closed
*/
@@ -48,6 +51,34 @@ static int pvfs_notify_destructor(void *ptr)
return 0;
}
+/*
+ send a reply to a pending notify request
+*/
+static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer)
+{
+ struct ntvfs_request *req = notify_buffer->req;
+ struct smb_notify *info = notify_buffer->info;
+
+ info->out.num_changes = notify_buffer->num_changes;
+ info->out.changes = talloc_steal(req, notify_buffer->changes);
+ notify_buffer->num_changes = 0;
+ notify_buffer->changes = NULL;
+ notify_buffer->current_buffer_size = 0;
+
+ notify_buffer->req = NULL;
+ notify_buffer->info = NULL;
+
+ DEBUG(0,("sending %d changes\n", info->out.num_changes));
+
+ if (info->out.num_changes == 0) {
+ req->async_states->status = NT_STATUS_CANCELLED;
+ } else {
+ req->async_states->status = NT_STATUS_OK;
+ }
+ req->async_states->send_fn(req);
+}
+
+
/*
called when a async notify event comes in
@@ -55,7 +86,17 @@ static int pvfs_notify_destructor(void *ptr)
static void pvfs_notify_callback(void *private, const struct notify_event *ev)
{
struct pvfs_notify_buffer *n = talloc_get_type(private, struct pvfs_notify_buffer);
- DEBUG(0,("got notify for '%s'\n", ev->path));
+
+ n->changes = talloc_realloc(n, n->changes, struct notify_changes, n->num_changes+1);
+ n->changes[n->num_changes].action = ev->action;
+ n->changes[n->num_changes].name.s = talloc_strdup(n->changes, ev->path);
+ n->num_changes++;
+
+ DEBUG(0,("got notify for '%s' action=%d\n", ev->path, ev->action));
+
+ if (n->req != NULL) {
+ pvfs_notify_send(n);
+ }
}
/*
@@ -86,6 +127,22 @@ static NTSTATUS pvfs_notify_setup(struct pvfs_state *pvfs, struct pvfs_file *f,
return NT_STATUS_OK;
}
+/*
+ called from the pvfs_wait code when either an event has come in, or
+ the notify request has been cancelled
+*/
+static void pvfs_notify_end(void *private, enum pvfs_wait_notice reason)
+{
+ struct pvfs_notify_buffer *notify_buffer = talloc_get_type(private, struct pvfs_notify_buffer);
+ struct ntvfs_request *req = notify_buffer->req;
+
+ if (req == NULL) {
+ /* nothing to do, nobody is waiting */
+ return;
+ }
+
+ pvfs_notify_send(notify_buffer);
+}
/* change notify request - always async. This request blocks until the
event buffer is non-empty */
@@ -110,7 +167,7 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
/* its only valid for directories */
if (f->handle->fd != -1) {
- return NT_STATUS_NOT_A_DIRECTORY;
+ return NT_STATUS_INVALID_PARAMETER;
}
/* if the handle doesn't currently have a notify buffer then
@@ -123,19 +180,27 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
NT_STATUS_NOT_OK_RETURN(status);
}
+ req->async_states->status = NT_STATUS_OK;
+
+ if (f->notify_buffer->req != NULL) {
+ DEBUG(0,("Notify already setup\n"));
+ pvfs_notify_send(f->notify_buffer);
+ }
+
+ f->notify_buffer->req = talloc_reference(f->notify_buffer, req);
+ f->notify_buffer->info = info;
+
/* if the buffer is empty then start waiting */
if (f->notify_buffer->num_changes == 0) {
- req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
+ void *wait_handle =
+ pvfs_wait_message(pvfs, req, -1, timeval_zero(),
+ pvfs_notify_end, f->notify_buffer);
+ NT_STATUS_HAVE_NO_MEMORY(wait_handle);
+ talloc_steal(req, wait_handle);
return NT_STATUS_OK;
}
- /* otherwise if the buffer is not empty then return its
- contents immediately */
- info->out.num_changes = f->notify_buffer->num_changes;
- info->out.changes = talloc_steal(req, f->notify_buffer->changes);
- f->notify_buffer->num_changes = 0;
- f->notify_buffer->changes = NULL;
- f->notify_buffer->current_buffer_size = 0;
+ pvfs_notify_send(f->notify_buffer);
return NT_STATUS_OK;
}
diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c
index 2d7e41c247..5750c0fe08 100644
--- a/source4/ntvfs/posix/pvfs_wait.c
+++ b/source4/ntvfs/posix/pvfs_wait.c
@@ -105,7 +105,9 @@ static void pvfs_wait_timeout(struct event_context *ev,
static int pvfs_wait_destructor(void *ptr)
{
struct pvfs_wait *pwait = ptr;
- messaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
+ if (pwait->msg_type != -1) {
+ messaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
+ }
DLIST_REMOVE(pwait->pvfs->wait_list, pwait);
return 0;
}
@@ -116,6 +118,9 @@ static int pvfs_wait_destructor(void *ptr)
the return value is a handle. To stop waiting talloc_free this
handle.
+
+ if msg_type == -1 then no message is registered, and it is assumed
+ that the caller handles any messaging setup needed
*/
void *pvfs_wait_message(struct pvfs_state *pvfs,
struct ntvfs_request *req,
@@ -146,10 +151,12 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
/* register with the messaging subsystem for this message
type */
- messaging_register(pwait->msg_ctx,
- pwait,
- msg_type,
- pvfs_wait_dispatch);
+ if (msg_type != -1) {
+ messaging_register(pwait->msg_ctx,
+ pwait,
+ msg_type,
+ pvfs_wait_dispatch);
+ }
/* tell the main smb server layer that we will be replying
asynchronously */