diff options
author | Andrew Tridgell <tridge@samba.org> | 2006-05-23 03:52:57 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:08:28 -0500 |
commit | ae034247efdd380ecf0588846ca2fe959e4d1e48 (patch) | |
tree | 571ae966586e6e2f43948f9f2901690a6603b190 | |
parent | 5da75f5c3631247615efdf73fae2481df6908cb8 (diff) | |
download | samba-ae034247efdd380ecf0588846ca2fe959e4d1e48.tar.gz samba-ae034247efdd380ecf0588846ca2fe959e4d1e48.tar.bz2 samba-ae034247efdd380ecf0588846ca2fe959e4d1e48.zip |
r15825: there are quite subtle semantics with change notify events being sent
when a context (such as a tree connect) is destroyed. The behaviour
was changed by the ntvfs memory leak fix, and this patch is needed to
make it all work again.
(This used to be commit a7ad4df7cd6cdf88fd49698840a072a4474a318a)
-rw-r--r-- | source4/ntvfs/posix/pvfs_notify.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/source4/ntvfs/posix/pvfs_notify.c b/source4/ntvfs/posix/pvfs_notify.c index dfe1737060..bd1e1b9d89 100644 --- a/source4/ntvfs/posix/pvfs_notify.c +++ b/source4/ntvfs/posix/pvfs_notify.c @@ -25,6 +25,7 @@ #include "lib/messaging/irpc.h" #include "messaging/messaging.h" #include "dlinklist.h" +#include "lib/events/events.h" /* pending notifies buffer, hung off struct pvfs_file for open directories that have used change notify */ @@ -44,9 +45,22 @@ struct pvfs_notify_buffer { }; /* + send a notify on the next event run. +*/ +void pvfs_notify_send_next(struct event_context *ev, struct timed_event *te, + struct timeval t, void *ptr) +{ + struct ntvfs_request *req = talloc_get_type(ptr, struct ntvfs_request); + talloc_free(req); + req->async_states->send_fn(req); +} + + +/* send a reply to a pending notify request */ -static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer, NTSTATUS status) +static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer, + NTSTATUS status, BOOL immediate) { struct notify_pending *pending = notify_buffer->pending; struct ntvfs_request *req; @@ -57,7 +71,7 @@ static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer, NTSTATUS /* on buffer overflow return no changes and destroys the notify buffer */ notify_buffer->num_changes = 0; while (notify_buffer->pending) { - pvfs_notify_send(notify_buffer, NT_STATUS_OK); + pvfs_notify_send(notify_buffer, NT_STATUS_OK, immediate); } talloc_free(notify_buffer); return; @@ -86,7 +100,18 @@ static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer, NTSTATUS } req->async_states->status = status; - req->async_states->send_fn(req); + + if (immediate) { + req->async_states->send_fn(req); + return; + } + + /* we can't call pvfs_notify_send() directly here, as that + would free the request, and the ntvfs modules above us + could use it, so call it on the next event */ + talloc_reference(notify_buffer, req); + event_add_timed(req->ctx->event_ctx, + req, timeval_zero(), pvfs_notify_send_next, req); } /* @@ -97,7 +122,7 @@ static int pvfs_notify_destructor(void *ptr) struct pvfs_notify_buffer *n = talloc_get_type(ptr, struct pvfs_notify_buffer); notify_remove(n->f->pvfs->notify_context, n); n->f->notify_buffer = NULL; - pvfs_notify_send(n, NT_STATUS_OK); + pvfs_notify_send(n, NT_STATUS_OK, True); return 0; } @@ -140,7 +165,7 @@ static void pvfs_notify_callback(void *private, const struct notify_event *ev) /* send what we have, unless its the first part of a rename */ if (ev->action != NOTIFY_ACTION_OLD_NAME) { - pvfs_notify_send(n, NT_STATUS_OK); + pvfs_notify_send(n, NT_STATUS_OK, True); } } @@ -185,9 +210,9 @@ 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); if (reason == PVFS_WAIT_CANCEL) { - pvfs_notify_send(notify_buffer, NT_STATUS_CANCELLED); + pvfs_notify_send(notify_buffer, NT_STATUS_CANCELLED, False); } else { - pvfs_notify_send(notify_buffer, NT_STATUS_OK); + pvfs_notify_send(notify_buffer, NT_STATUS_OK, True); } } @@ -251,7 +276,8 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs, return NT_STATUS_OK; } - pvfs_notify_send(f->notify_buffer, NT_STATUS_OK); + req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; + pvfs_notify_send(f->notify_buffer, NT_STATUS_OK, False); return NT_STATUS_OK; } |