summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix/pvfs_notify.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/ntvfs/posix/pvfs_notify.c')
-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;
}