summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix
diff options
context:
space:
mode:
Diffstat (limited to 'source4/ntvfs/posix')
-rw-r--r--source4/ntvfs/posix/pvfs_open.c1
-rw-r--r--source4/ntvfs/posix/pvfs_wait.c31
-rw-r--r--source4/ntvfs/posix/vfs_posix.c1
-rw-r--r--source4/ntvfs/posix/vfs_posix.h4
4 files changed, 36 insertions, 1 deletions
diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c
index 8ad6ad0389..2c0f55cf22 100644
--- a/source4/ntvfs/posix/pvfs_open.c
+++ b/source4/ntvfs/posix/pvfs_open.c
@@ -556,7 +556,6 @@ static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req,
}
talloc_free(lck);
- talloc_steal(pvfs, req);
talloc_set_destructor(r, pvfs_retry_destructor);
diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c
index 0faab8ef55..df7f045e00 100644
--- a/source4/ntvfs/posix/pvfs_wait.c
+++ b/source4/ntvfs/posix/pvfs_wait.c
@@ -22,10 +22,13 @@
#include "include/includes.h"
#include "events.h"
+#include "dlinklist.h"
#include "vfs_posix.h"
/* the context for a single wait instance */
struct pvfs_wait {
+ struct pvfs_wait *next, *prev;
+ struct pvfs_state *pvfs;
void (*handler)(void *, BOOL);
void *private;
struct timed_event *te;
@@ -103,6 +106,7 @@ static int pvfs_wait_destructor(void *ptr)
struct pvfs_wait *pwait = ptr;
messaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
event_remove_timed(pwait->ev, pwait->te);
+ DLIST_REMOVE(pwait->pvfs->wait_list, pwait);
return 0;
}
@@ -134,6 +138,7 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
pwait->ev = req->tcon->smb_conn->connection->event.ctx;
pwait->msg_type = msg_type;
pwait->req = req;
+ pwait->pvfs = pvfs;
/* setup a timer */
te.next_event = end_time;
@@ -152,8 +157,34 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
asynchronously */
req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
+ DLIST_ADD(pvfs->wait_list, pwait);
+
/* make sure we cleanup the timer and message handler */
talloc_set_destructor(pwait, pvfs_wait_destructor);
+ /* make sure that on a disconnect the request is not destroyed
+ before pvfs */
+ talloc_steal(pvfs, req);
+
return pwait;
}
+
+
+/*
+ cancel an outstanding async request
+*/
+NTSTATUS pvfs_cancel(struct ntvfs_module_context *ntvfs, struct smbsrv_request *req)
+{
+ struct pvfs_state *pvfs = ntvfs->private_data;
+ struct pvfs_wait *pwait;
+ for (pwait=pvfs->wait_list;pwait;pwait=pwait->next) {
+ if (SVAL(req->in.hdr, HDR_MID) == SVAL(pwait->req->in.hdr, HDR_MID) &&
+ req->smbpid == pwait->req->smbpid) {
+ /* trigger an early timeout */
+ pvfs_wait_timeout(pwait->ev, pwait->te, timeval_current());
+ return NT_STATUS_OK;
+ }
+ }
+
+ return NT_STATUS_UNSUCCESSFUL;
+}
diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c
index 7ebea2ea9a..9ad1d3cb35 100644
--- a/source4/ntvfs/posix/vfs_posix.c
+++ b/source4/ntvfs/posix/vfs_posix.c
@@ -236,6 +236,7 @@ NTSTATUS ntvfs_posix_init(void)
ops.trans = pvfs_trans;
ops.logoff = pvfs_logoff;
ops.async_setup = pvfs_async_setup;
+ ops.cancel = pvfs_cancel;
/* register ourselves with the NTVFS subsystem. We register
under the name 'default' as we wish to be the default
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 265649f5a3..ce6e7ad24d 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -46,6 +46,10 @@ struct pvfs_state {
/* an id tree mapping open file handle -> struct pvfs_file */
struct idr_context *idtree_fnum;
+
+ /* a list of pending async requests. Needed to support
+ ntcancel */
+ struct pvfs_wait *wait_list;
};