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)
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
*/
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;
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
*/
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);
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
*/
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 */
/* 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 {
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)
}
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);
+}
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
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
*(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);
}
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);
}
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;
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
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
*/
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'
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
*/
ops.search_close = unixuid_search_close;
ops.trans = unixuid_trans;
ops.logoff = unixuid_logoff;
+ ops.async_setup = unixuid_async_setup;
ops.name = "unixuid";