s3:smbd: use lp_smbd_search_ask_sharemode()
[Samba.git] / source3 / modules / vfs_delay_inject.c
blobd561fadb03be28f7936163eb52152e3761d52874
1 /*
2 * Unix SMB/CIFS implementation.
3 * Samba VFS module for delay injection in VFS calls
4 * Copyright (C) Ralph Boehme 2018
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "smbd/smbd.h"
22 #include "lib/util/tevent_unix.h"
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_VFS
27 static void inject_delay(const char *vfs_func, vfs_handle_struct *handle)
29 int delay;
31 delay = lp_parm_int(SNUM(handle->conn), "delay_inject", vfs_func, 0);
32 if (delay == 0) {
33 return;
36 DBG_DEBUG("Injected delay for [%s] of [%d] ms\n", vfs_func, delay);
38 smb_msleep(delay);
41 static int vfs_delay_inject_ntimes(vfs_handle_struct *handle,
42 const struct smb_filename *smb_fname,
43 struct smb_file_time *ft)
45 inject_delay("ntimes", handle);
47 return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
50 struct vfs_delay_inject_pread_state {
51 struct tevent_context *ev;
52 struct vfs_handle_struct *handle;
53 struct files_struct *fsp;
54 void *data;
55 size_t n;
56 off_t offset;
57 ssize_t ret;
58 struct vfs_aio_state vfs_aio_state;
61 static void vfs_delay_inject_pread_wait_done(struct tevent_req *subreq);
62 static void vfs_delay_inject_pread_done(struct tevent_req *subreq);
64 static struct tevent_req *vfs_delay_inject_pread_send(
65 struct vfs_handle_struct *handle,
66 TALLOC_CTX *mem_ctx,
67 struct tevent_context *ev,
68 struct files_struct *fsp,
69 void *data,
70 size_t n,
71 off_t offset)
73 struct tevent_req *req = NULL, *subreq = NULL;
74 struct vfs_delay_inject_pread_state *state = NULL;
75 int delay;
76 struct timeval delay_tv;
78 delay = lp_parm_int(
79 SNUM(handle->conn), "delay_inject", "pread_send", 0);
80 delay_tv = tevent_timeval_current_ofs(delay / 1000,
81 (delay * 1000) % 1000000);
83 req = tevent_req_create(mem_ctx, &state,
84 struct vfs_delay_inject_pread_state);
85 if (req == NULL) {
86 return NULL;
88 *state = (struct vfs_delay_inject_pread_state) {
89 .ev = ev,
90 .handle = handle,
91 .fsp = fsp,
92 .data = data,
93 .n = n,
94 .offset = offset,
97 if (delay == 0) {
98 subreq = SMB_VFS_NEXT_PREAD_SEND(state,
99 state->ev,
100 state->handle,
101 state->fsp,
102 state->data,
103 state->n,
104 state->offset);
105 if (tevent_req_nomem(subreq, req)) {
106 return tevent_req_post(req, ev);
108 tevent_req_set_callback(subreq,
109 vfs_delay_inject_pread_done,
110 req);
111 return req;
114 subreq = tevent_wakeup_send(state, ev, delay_tv);
115 if (tevent_req_nomem(subreq, req)) {
116 return tevent_req_post(req, ev);
118 tevent_req_set_callback(subreq, vfs_delay_inject_pread_wait_done, req);
119 return req;
123 static void vfs_delay_inject_pread_wait_done(struct tevent_req *subreq)
125 struct tevent_req *req = tevent_req_callback_data(
126 subreq, struct tevent_req);
127 struct vfs_delay_inject_pread_state *state = tevent_req_data(
128 req, struct vfs_delay_inject_pread_state);
129 bool ok;
131 ok = tevent_wakeup_recv(subreq);
132 TALLOC_FREE(subreq);
133 if (!ok) {
134 tevent_req_error(req, EIO);
135 return;
138 subreq = SMB_VFS_NEXT_PREAD_SEND(state,
139 state->ev,
140 state->handle,
141 state->fsp,
142 state->data,
143 state->n,
144 state->offset);
145 if (tevent_req_nomem(subreq, req)) {
146 return;
148 tevent_req_set_callback(subreq, vfs_delay_inject_pread_done, req);
151 static void vfs_delay_inject_pread_done(struct tevent_req *subreq)
153 struct tevent_req *req = tevent_req_callback_data(
154 subreq, struct tevent_req);
155 struct vfs_delay_inject_pread_state *state = tevent_req_data(
156 req, struct vfs_delay_inject_pread_state);
158 state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
159 TALLOC_FREE(subreq);
161 tevent_req_done(req);
164 static ssize_t vfs_delay_inject_pread_recv(struct tevent_req *req,
165 struct vfs_aio_state *vfs_aio_state)
167 struct vfs_delay_inject_pread_state *state = tevent_req_data(
168 req, struct vfs_delay_inject_pread_state);
170 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
171 return -1;
174 *vfs_aio_state = state->vfs_aio_state;
175 return state->ret;
178 struct vfs_delay_inject_pwrite_state {
179 struct tevent_context *ev;
180 struct vfs_handle_struct *handle;
181 struct files_struct *fsp;
182 const void *data;
183 size_t n;
184 off_t offset;
185 ssize_t ret;
186 struct vfs_aio_state vfs_aio_state;
189 static void vfs_delay_inject_pwrite_wait_done(struct tevent_req *subreq);
190 static void vfs_delay_inject_pwrite_done(struct tevent_req *subreq);
192 static struct tevent_req *vfs_delay_inject_pwrite_send(
193 struct vfs_handle_struct *handle,
194 TALLOC_CTX *mem_ctx,
195 struct tevent_context *ev,
196 struct files_struct *fsp,
197 const void *data,
198 size_t n,
199 off_t offset)
201 struct tevent_req *req = NULL, *subreq = NULL;
202 struct vfs_delay_inject_pwrite_state *state = NULL;
203 int delay;
204 struct timeval delay_tv;
206 delay = lp_parm_int(
207 SNUM(handle->conn), "delay_inject", "pwrite_send", 0);
208 delay_tv = tevent_timeval_current_ofs(delay / 1000,
209 (delay * 1000) % 1000000);
211 req = tevent_req_create(mem_ctx, &state,
212 struct vfs_delay_inject_pwrite_state);
213 if (req == NULL) {
214 return NULL;
216 *state = (struct vfs_delay_inject_pwrite_state) {
217 .ev = ev,
218 .handle = handle,
219 .fsp = fsp,
220 .data = data,
221 .n = n,
222 .offset = offset,
225 if (delay == 0) {
226 subreq = SMB_VFS_NEXT_PWRITE_SEND(state,
227 state->ev,
228 state->handle,
229 state->fsp,
230 state->data,
231 state->n,
232 state->offset);
233 if (tevent_req_nomem(subreq, req)) {
234 return tevent_req_post(req, ev);
236 tevent_req_set_callback(subreq,
237 vfs_delay_inject_pwrite_done,
238 req);
239 return req;
242 subreq = tevent_wakeup_send(state, ev, delay_tv);
243 if (tevent_req_nomem(subreq, req)) {
244 return tevent_req_post(req, ev);
246 tevent_req_set_callback(
247 subreq, vfs_delay_inject_pwrite_wait_done, req);
248 return req;
252 static void vfs_delay_inject_pwrite_wait_done(struct tevent_req *subreq)
254 struct tevent_req *req = tevent_req_callback_data(
255 subreq, struct tevent_req);
256 struct vfs_delay_inject_pwrite_state *state = tevent_req_data(
257 req, struct vfs_delay_inject_pwrite_state);
258 bool ok;
260 ok = tevent_wakeup_recv(subreq);
261 TALLOC_FREE(subreq);
262 if (!ok) {
263 tevent_req_error(req, EIO);
264 return;
267 subreq = SMB_VFS_NEXT_PWRITE_SEND(state,
268 state->ev,
269 state->handle,
270 state->fsp,
271 state->data,
272 state->n,
273 state->offset);
274 if (tevent_req_nomem(subreq, req)) {
275 return;
277 tevent_req_set_callback(subreq, vfs_delay_inject_pwrite_done, req);
280 static void vfs_delay_inject_pwrite_done(struct tevent_req *subreq)
282 struct tevent_req *req = tevent_req_callback_data(
283 subreq, struct tevent_req);
284 struct vfs_delay_inject_pwrite_state *state = tevent_req_data(
285 req, struct vfs_delay_inject_pwrite_state);
287 state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
288 TALLOC_FREE(subreq);
290 tevent_req_done(req);
293 static ssize_t vfs_delay_inject_pwrite_recv(struct tevent_req *req,
294 struct vfs_aio_state *vfs_aio_state)
296 struct vfs_delay_inject_pwrite_state *state = tevent_req_data(
297 req, struct vfs_delay_inject_pwrite_state);
299 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
300 return -1;
303 *vfs_aio_state = state->vfs_aio_state;
304 return state->ret;
307 static struct vfs_fn_pointers vfs_delay_inject_fns = {
308 .ntimes_fn = vfs_delay_inject_ntimes,
309 .pread_send_fn = vfs_delay_inject_pread_send,
310 .pread_recv_fn = vfs_delay_inject_pread_recv,
311 .pwrite_send_fn = vfs_delay_inject_pwrite_send,
312 .pwrite_recv_fn = vfs_delay_inject_pwrite_recv,
315 static_decl_vfs;
316 NTSTATUS vfs_delay_inject_init(TALLOC_CTX *ctx)
318 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "delay_inject",
319 &vfs_delay_inject_fns);