summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-05-23 03:52:57 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:08:28 -0500
commitae034247efdd380ecf0588846ca2fe959e4d1e48 (patch)
tree571ae966586e6e2f43948f9f2901690a6603b190
parent5da75f5c3631247615efdf73fae2481df6908cb8 (diff)
downloadsamba-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.c42
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;
}