summaryrefslogtreecommitdiff
path: root/source4/ntvfs
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-03-30 02:25:38 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:59:19 -0500
commit0d3a9493a27e7724a5c0337a5f93037114990956 (patch)
treea56c88b5c8aa1053f8d16556054e548846810c84 /source4/ntvfs
parent8e7078e14964f6332f2d786baa1bb9bb6b4b1717 (diff)
downloadsamba-0d3a9493a27e7724a5c0337a5f93037114990956.tar.gz
samba-0d3a9493a27e7724a5c0337a5f93037114990956.tar.bz2
samba-0d3a9493a27e7724a5c0337a5f93037114990956.zip
r14795: queue notify requests on the same handle
(This used to be commit c976f14a9f397802946a9bb36394fe4c27bf3caf)
Diffstat (limited to 'source4/ntvfs')
-rw-r--r--source4/ntvfs/posix/pvfs_notify.c63
1 files changed, 31 insertions, 32 deletions
diff --git a/source4/ntvfs/posix/pvfs_notify.c b/source4/ntvfs/posix/pvfs_notify.c
index 01a88f25a7..a41a2d3cd2 100644
--- a/source4/ntvfs/posix/pvfs_notify.c
+++ b/source4/ntvfs/posix/pvfs_notify.c
@@ -24,6 +24,7 @@
#include "vfs_posix.h"
#include "lib/messaging/irpc.h"
#include "messaging/messaging.h"
+#include "dlinklist.h"
/* pending notifies buffer, hung off struct pvfs_file for open directories
that have used change notify */
@@ -33,11 +34,13 @@ struct pvfs_notify_buffer {
struct notify_changes *changes;
uint32_t max_buffer_size;
uint32_t current_buffer_size;
-
- /* these last two are only present when a notify request is
- pending */
- struct ntvfs_request *req;
- struct smb_notify *info;
+
+ /* a list of requests waiting for events on this handle */
+ struct notify_pending {
+ struct notify_pending *next, *prev;
+ struct ntvfs_request *req;
+ struct smb_notify *info;
+ } *pending;
};
/*
@@ -45,17 +48,24 @@ struct pvfs_notify_buffer {
*/
static void pvfs_notify_send(struct pvfs_notify_buffer *notify_buffer, NTSTATUS status)
{
- struct ntvfs_request *req = notify_buffer->req;
- struct smb_notify *info = notify_buffer->info;
+ struct notify_pending *pending = notify_buffer->pending;
+ struct ntvfs_request *req;
+ struct smb_notify *info;
+
+ if (pending == NULL) return;
+
+ DLIST_REMOVE(notify_buffer->pending, pending);
+
+ req = pending->req;
+ info = pending->info;
info->out.num_changes = notify_buffer->num_changes;
info->out.changes = talloc_steal(req, notify_buffer->changes);
notify_buffer->num_changes = 0;
notify_buffer->changes = NULL;
notify_buffer->current_buffer_size = 0;
-
- notify_buffer->req = NULL;
- notify_buffer->info = NULL;
+
+ talloc_free(pending);
DEBUG(0,("sending %d changes\n", info->out.num_changes));
@@ -75,9 +85,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;
- if (n->req) {
- pvfs_notify_send(n, NT_STATUS_OK);
- }
+ pvfs_notify_send(n, NT_STATUS_OK);
return 0;
}
@@ -96,9 +104,7 @@ static void pvfs_notify_callback(void *private, const struct notify_event *ev)
DEBUG(0,("got notify for '%s' action=%d\n", ev->path, ev->action));
- if (n->req != NULL) {
- pvfs_notify_send(n, NT_STATUS_OK);
- }
+ pvfs_notify_send(n, NT_STATUS_OK);
}
/*
@@ -135,14 +141,8 @@ static NTSTATUS pvfs_notify_setup(struct pvfs_state *pvfs, struct pvfs_file *f,
*/
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);
- struct ntvfs_request *req = notify_buffer->req;
-
- if (req == NULL) {
- /* nothing to do, nobody is waiting */
- return;
- }
-
+ 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);
} else {
@@ -160,6 +160,7 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
struct pvfs_state);
struct pvfs_file *f;
NTSTATUS status;
+ struct notify_pending *pending;
f = pvfs_find_fd(pvfs, req, info->in.file.fnum);
if (!f) {
@@ -186,15 +187,13 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs,
NT_STATUS_NOT_OK_RETURN(status);
}
- req->async_states->status = NT_STATUS_OK;
-
- if (f->notify_buffer->req != NULL) {
- DEBUG(0,("Notify already setup\n"));
- pvfs_notify_send(f->notify_buffer, NT_STATUS_CANCELLED);
- }
+ pending = talloc(f->notify_buffer, struct notify_pending);
+ NT_STATUS_HAVE_NO_MEMORY(pending);
+
+ pending->req = talloc_reference(pending, req);
+ pending->info = info;
- f->notify_buffer->req = talloc_reference(f->notify_buffer, req);
- f->notify_buffer->info = info;
+ DLIST_ADD_END(f->notify_buffer->pending, pending, struct notify_pending *);
/* if the buffer is empty then start waiting */
if (f->notify_buffer->num_changes == 0) {