r3039: This solves the problem of async handlers in ntvfs backends not being
authorAndrew Tridgell <tridge@samba.org>
Mon, 18 Oct 2004 13:27:22 +0000 (13:27 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:00:01 +0000 (13:00 -0500)
in the right state when called. For example, when we use the unixuid
handler in the chain of handlers, and a backend decides to continue a
call asynchronously then we need to ensure that the continuation
happens with the right security context.

The solution is to add a new ntvfs operation ntvfs_async_setup(),
which calls all the way down through the layers, setting up anything
that is required, and takes a private pointer. The backend wanting to
make a async calls can use ntvfs_async_setup() to ensure that the
modules above it are called when doing async processing.
(This used to be commit a256e71029727fa1659ade6257085df537308c7d)

source4/ntvfs/cifs/vfs_cifs.c
source4/ntvfs/ipc/vfs_ipc.c
source4/ntvfs/nbench/vfs_nbench.c
source4/ntvfs/ntvfs.h
source4/ntvfs/ntvfs_interface.c
source4/ntvfs/posix/pvfs_wait.c
source4/ntvfs/posix/vfs_posix.c
source4/ntvfs/simple/vfs_simple.c
source4/ntvfs/unixuid/vfs_unixuid.c

index 7c4a1d79d6dc9da960d2fe10dcc766b02fd8aca5..5b10e7241161d5eb74858ef1149ac085c680ecdf 100644 (file)
@@ -563,6 +563,16 @@ static NTSTATUS cvfs_logoff(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_OK;
 }
 
+/*
+  setup for an async call - nothing to do yet
+*/
+static NTSTATUS cvfs_async_setup(struct ntvfs_module_context *ntvfs, 
+                                struct smbsrv_request *req, 
+                                void *private)
+{
+       return NT_STATUS_OK;
+}
+
 /*
   lock a byte range
 */
@@ -748,6 +758,7 @@ NTSTATUS ntvfs_cifs_init(void)
        ops.search_close = cvfs_search_close;
        ops.trans = cvfs_trans;
        ops.logoff = cvfs_logoff;
+       ops.async_setup = cvfs_async_setup;
 
        if (lp_parm_bool(-1, "cifs", "maptrans2", False)) {
                ops.trans2 = cvfs_trans2;
index 69fed6f86f8a4d9ba72b66e6115a58e8bd42f8b1..b37b3e917daa706888c01644a59350b5347c3cbe 100644 (file)
@@ -571,6 +571,16 @@ static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_OK;
 }
 
+/*
+  setup for an async call
+*/
+static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
+                               struct smbsrv_request *req,
+                               void *private)
+{
+       return NT_STATUS_OK;
+}
+
 /*
   lock a byte range
 */
@@ -795,6 +805,7 @@ NTSTATUS ntvfs_ipc_init(void)
        ops.search_close = ipc_search_close;
        ops.trans = ipc_trans;
        ops.logoff = ipc_logoff;
+       ops.async_setup = ipc_async_setup;
 
        /* register ourselves with the NTVFS subsystem. */
        ret = register_backend("ntvfs", &ops);
index 06c237afb5e62decc4c1a9d519d48340458af326..6203c21506da6aba5b2c2cfe2ef6c66bb250efe3 100644 (file)
@@ -489,6 +489,16 @@ static NTSTATUS nbench_logoff(struct ntvfs_module_context *ntvfs,
        return status;
 }
 
+/*
+  async setup
+*/
+static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
+                                  struct smbsrv_request *req,
+                                  void *private)
+{
+       return NT_STATUS_OK;
+}
+
 /*
   lock a byte range
 */
@@ -695,6 +705,7 @@ NTSTATUS ntvfs_nbench_init(void)
        ops.search_close = nbench_search_close;
        ops.trans = nbench_trans;
        ops.logoff = nbench_logoff;
+       ops.async_setup = nbench_async_setup;
 
        /* we don't register a trans2 handler as we want to be able to
           log individual trans2 requests */
index bee10e3c3856fb849cac2fcbd80c34ef377f0a44..c9fe276f5441850d235e98d438bbbcaa10414660 100644 (file)
@@ -112,7 +112,11 @@ struct ntvfs_ops {
 
        /* logoff - called when a vuid is closed */
        NTSTATUS (*logoff)(struct ntvfs_module_context *ntvfs, 
-                               struct smbsrv_request *req);
+                          struct smbsrv_request *req);
+
+       /* async_setup - called when a backend is processing a async request */
+       NTSTATUS (*async_setup)(struct ntvfs_module_context *ntvfs, 
+                               struct smbsrv_request *req, void *private);
 };
 
 struct ntvfs_module_context {
index 06cda11000bb1123450be3e779680c1f75afe369..7ba1c0d6bee3fde6f871b35dc1115de11bc2422d 100644 (file)
@@ -293,6 +293,17 @@ NTSTATUS ntvfs_logoff(struct smbsrv_request *req)
        return ntvfs->ops->logoff(ntvfs, req);
 }
 
+/* async setup - called by a backend that wants to setup any state for
+   a async request */
+NTSTATUS ntvfs_async_setup(struct smbsrv_request *req, void *private)
+{
+       struct ntvfs_module_context *ntvfs = req->tcon->ntvfs_ctx->modules;
+       if (!ntvfs->ops->async_setup) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+       return ntvfs->ops->async_setup(ntvfs, req, private);
+}
+
 /* initial setup */
 NTSTATUS ntvfs_next_connect(struct ntvfs_module_context *ntvfs, 
                            struct smbsrv_request *req, const char *sharename)
@@ -564,3 +575,14 @@ NTSTATUS ntvfs_next_logoff(struct ntvfs_module_context *ntvfs,
        }
        return ntvfs->next->ops->logoff(ntvfs->next, req);
 }
+
+/* async_setup - called when setting up for a async request */
+NTSTATUS ntvfs_next_async_setup(struct ntvfs_module_context *ntvfs, 
+                               struct smbsrv_request *req, 
+                               void *private)
+{
+       if (!ntvfs->next || !ntvfs->next->ops->async_setup) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+       return ntvfs->next->ops->async_setup(ntvfs->next, req, private);
+}
index 5815b8eddead4cd9d34b56981965b9e26a854b82..2a4a1d286b6b099ea2b8cc3eddb8656983e2abe9 100644 (file)
@@ -31,8 +31,22 @@ struct pvfs_wait {
        int msg_type;
        void *msg_ctx;
        struct event_context *ev;
+       struct smbsrv_request *req;
+       BOOL timed_out;
 };
 
+/*
+  called from the ntvfs layer when we have requested setup of an async
+  call.  this ensures that async calls runs with the right state of
+  previous ntvfs handlers in the chain (such as security context)
+*/
+NTSTATUS pvfs_async_setup(struct ntvfs_module_context *ntvfs,
+                         struct smbsrv_request *req, void *private)
+{
+       struct pvfs_wait *pwait = private;
+       pwait->handler(pwait->private, pwait->timed_out);
+       return NT_STATUS_OK;
+}
 
 /*
   receive a completion message for a wait
@@ -41,6 +55,7 @@ static void pvfs_wait_dispatch(void *msg_ctx, void *private, uint32_t msg_type,
                               servid_t src, DATA_BLOB *data)
 {
        struct pvfs_wait *pwait = private;
+       struct smbsrv_request *req;
 
        /* we need to check that this one is for us. This sender sends
           the private pointer as the body of the message. This might
@@ -50,8 +65,16 @@ static void pvfs_wait_dispatch(void *msg_ctx, void *private, uint32_t msg_type,
            *(void **)data->data != pwait->private) {
                return;
        }
-
-       pwait->handler(pwait->private, False);
+       pwait->timed_out = False;
+       req = pwait->req;
+
+       /* the extra reference here is to ensure that the req
+          structure is not destroyed when the async request reply is
+          sent, which would cause problems with the other ntvfs
+          modules above us */
+       talloc_increase_ref_count(req);
+       ntvfs_async_setup(pwait->req, pwait);
+       talloc_free(req);
 }
 
 
@@ -61,7 +84,13 @@ static void pvfs_wait_dispatch(void *msg_ctx, void *private, uint32_t msg_type,
 static void pvfs_wait_timeout(struct event_context *ev, struct timed_event *te, time_t t)
 {
        struct pvfs_wait *pwait = te->private;
-       pwait->handler(pwait->private, True);
+       struct smbsrv_request *req = pwait->req;
+
+       pwait->timed_out = True;
+
+       talloc_increase_ref_count(req);
+       ntvfs_async_setup(pwait->req, pwait);
+       talloc_free(req);
 }
 
 
@@ -103,6 +132,7 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
        pwait->msg_ctx = pvfs->tcon->smb_conn->connection->messaging_ctx;
        pwait->ev = req->tcon->smb_conn->connection->event.ctx;
        pwait->msg_type = msg_type;
+       pwait->req = req;
 
        /* setup a timer */
        te.next_event = end_time;
index 6e6c8b4275a9068bd86858d6a1b811b9e9c8b22e..e989f8de676a5a044f6d4ce788fc324463935d03 100644 (file)
@@ -237,6 +237,7 @@ NTSTATUS ntvfs_posix_init(void)
        ops.search_close = pvfs_search_close;
        ops.trans = pvfs_trans;
        ops.logoff = pvfs_logoff;
+       ops.async_setup = pvfs_async_setup;
 
        /* register ourselves with the NTVFS subsystem. We register
           under the name 'default' as we wish to be the default
index 7f5d447a09c743c25475d63aa07007a5584e3802..7ebc040608bd20836d17688e80b5ce860e6e5451 100644 (file)
@@ -622,6 +622,16 @@ static NTSTATUS svfs_logoff(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_NOT_SUPPORTED;
 }
 
+/*
+  setup for an async call
+*/
+static NTSTATUS svfs_async_setup(struct ntvfs_module_context *ntvfs,
+                                struct smbsrv_request *req, 
+                                void *private)
+{
+       return NT_STATUS_OK;
+}
+
 /*
   lock a byte range
 */
@@ -999,6 +1009,7 @@ NTSTATUS ntvfs_simple_init(void)
        ops.search_close = svfs_search_close;
        ops.trans = svfs_trans;
        ops.logoff = svfs_logoff;
+       ops.async_setup = svfs_async_setup;
 
        /* register ourselves with the NTVFS subsystem. We register
           under names 'simple'
index 542b011c67d616031d39a58514724a88b8fc29bc..d0060bf11d7ef5ff6642b91008ff78f3f2348ea0 100644 (file)
@@ -624,6 +624,20 @@ static NTSTATUS unixuid_logoff(struct ntvfs_module_context *ntvfs,
        return status;
 }
 
+/*
+  async setup
+*/
+static NTSTATUS unixuid_async_setup(struct ntvfs_module_context *ntvfs,
+                                   struct smbsrv_request *req, 
+                                   void *private)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, async_setup, (ntvfs, req, private));
+
+       return status;
+}
+
 /*
   lock a byte range
 */
@@ -767,6 +781,7 @@ NTSTATUS ntvfs_unixuid_init(void)
        ops.search_close = unixuid_search_close;
        ops.trans = unixuid_trans;
        ops.logoff = unixuid_logoff;
+       ops.async_setup = unixuid_async_setup;
 
        ops.name = "unixuid";