From ae034247efdd380ecf0588846ca2fe959e4d1e48 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 23 May 2006 03:52:57 +0000 Subject: 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) --- source4/ntvfs/posix/pvfs_notify.c | 42 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_notify.c') 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 */ @@ -43,10 +44,23 @@ struct pvfs_notify_buffer { } *pending; }; +/* + 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; } -- cgit