ctdb-server: Remove duplicate logic
[samba4-gss.git] / source4 / ntvfs / posix / pvfs_wait.c
blob21ff33e28f796df4a48c29c067606a4f21a506e2
1 /*
2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - async request wait routines
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "lib/events/events.h"
24 #include "../lib/util/dlinklist.h"
25 #include "vfs_posix.h"
26 #include "samba/service_stream.h"
27 #include "lib/messaging/irpc.h"
29 /* the context for a single wait instance */
30 struct pvfs_wait {
31 struct pvfs_wait *next, *prev;
32 struct pvfs_state *pvfs;
33 void (*handler)(void *, enum pvfs_wait_notice);
34 void *private_data;
35 int msg_type;
36 struct imessaging_context *msg_ctx;
37 struct tevent_context *ev;
38 struct ntvfs_request *req;
39 enum pvfs_wait_notice reason;
43 called from the ntvfs layer when we have requested setup of an async
44 call. this ensures that async calls runs with the right state of
45 previous ntvfs handlers in the chain (such as security context)
47 NTSTATUS pvfs_async_setup(struct ntvfs_module_context *ntvfs,
48 struct ntvfs_request *req, void *private_data)
50 struct pvfs_wait *pwait = talloc_get_type(private_data,
51 struct pvfs_wait);
52 pwait->handler(pwait->private_data, pwait->reason);
53 return NT_STATUS_OK;
57 receive a completion message for a wait
59 static void pvfs_wait_dispatch(struct imessaging_context *msg,
60 void *private_data,
61 uint32_t msg_type,
62 struct server_id src,
63 size_t num_fds,
64 int *fds,
65 DATA_BLOB *data)
67 struct pvfs_wait *pwait = talloc_get_type(private_data,
68 struct pvfs_wait);
69 struct ntvfs_request *req;
70 void *p = NULL;
72 if (num_fds != 0) {
73 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
74 return;
77 /* we need to check that this one is for us. See
78 imessaging_send_ptr() for the other side of this.
80 if (data->length == sizeof(void *)) {
81 void **pp;
82 pp = (void **)data->data;
83 p = *pp;
85 if (p == NULL || p != pwait->private_data) {
86 return;
89 pwait->reason = PVFS_WAIT_EVENT;
91 /* the extra reference here is to ensure that the req
92 structure is not destroyed when the async request reply is
93 sent, which would cause problems with the other ntvfs
94 modules above us */
95 req = talloc_reference(msg, pwait->req);
96 ntvfs_async_setup(pwait->req, pwait);
97 talloc_unlink(msg, req);
102 receive a timeout on a message wait
104 static void pvfs_wait_timeout(struct tevent_context *ev,
105 struct tevent_timer *te, struct timeval t,
106 void *private_data)
108 struct pvfs_wait *pwait = talloc_get_type(private_data,
109 struct pvfs_wait);
110 struct ntvfs_request *req = pwait->req;
112 pwait->reason = PVFS_WAIT_TIMEOUT;
114 req = talloc_reference(ev, req);
115 if (req != NULL) {
116 ntvfs_async_setup(req, pwait);
117 talloc_unlink(ev, req);
123 destroy a pending wait
125 static int pvfs_wait_destructor(struct pvfs_wait *pwait)
127 if (pwait->msg_type != -1) {
128 imessaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
130 DLIST_REMOVE(pwait->pvfs->wait_list, pwait);
131 return 0;
135 setup a request to wait on a message of type msg_type, with a
136 timeout (given as an expiry time)
138 the return value is a handle. To stop waiting talloc_free this
139 handle.
141 if msg_type == -1 then no message is registered, and it is assumed
142 that the caller handles any messaging setup needed
144 struct pvfs_wait *pvfs_wait_message(struct pvfs_state *pvfs,
145 struct ntvfs_request *req,
146 int msg_type,
147 struct timeval end_time,
148 void (*fn)(void *, enum pvfs_wait_notice),
149 void *private_data)
151 struct pvfs_wait *pwait;
153 pwait = talloc(pvfs, struct pvfs_wait);
154 if (pwait == NULL) {
155 return NULL;
158 pwait->private_data = private_data;
159 pwait->handler = fn;
160 pwait->msg_ctx = pvfs->ntvfs->ctx->msg_ctx;
161 pwait->ev = pvfs->ntvfs->ctx->event_ctx;
162 pwait->msg_type = msg_type;
163 pwait->req = talloc_reference(pwait, req);
164 pwait->pvfs = pvfs;
166 if (!timeval_is_zero(&end_time)) {
167 /* setup a timer */
168 tevent_add_timer(pwait->ev, pwait, end_time, pvfs_wait_timeout, pwait);
171 /* register with the messaging subsystem for this message
172 type */
173 if (msg_type != -1) {
174 imessaging_register(pwait->msg_ctx,
175 pwait,
176 msg_type,
177 pvfs_wait_dispatch);
180 /* tell the main smb server layer that we will be replying
181 asynchronously */
182 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
184 DLIST_ADD(pvfs->wait_list, pwait);
186 /* make sure we cleanup the timer and message handler */
187 talloc_set_destructor(pwait, pvfs_wait_destructor);
189 return pwait;
194 cancel an outstanding async request
196 NTSTATUS pvfs_cancel(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req)
198 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
199 struct pvfs_state);
200 struct pvfs_wait *pwait;
202 for (pwait=pvfs->wait_list;pwait;pwait=pwait->next) {
203 if (pwait->req == req) {
204 /* trigger a cancel on the request */
205 pwait->reason = PVFS_WAIT_CANCEL;
206 ntvfs_async_setup(pwait->req, pwait);
207 return NT_STATUS_OK;
211 return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);