Author: tridge Date: 2006-05-23 03:52:57 +0000 (Tue, 23 May 2006) New Revision: 15825
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15825 Log: 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. Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c Changeset: Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c =================================================================== --- branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c 2006-05-23 03:51:44 UTC (rev 15824) +++ branches/SAMBA_4_0/source/ntvfs/posix/pvfs_notify.c 2006-05-23 03:52:57 UTC (rev 15825) @@ -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 @@ }; /* + 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 @@ /* 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 @@ } 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 @@ 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 @@ /* 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 @@ 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 @@ 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; }