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/>.
21 #include "smbd/smbd.h"
22 #include "lib/util/tevent_unix.h"
25 #define DBGC_CLASS DBGC_VFS
27 static void inject_delay(const char *vfs_func
, vfs_handle_struct
*handle
)
31 delay
= lp_parm_int(SNUM(handle
->conn
), "delay_inject", vfs_func
, 0);
36 DBG_DEBUG("Injected delay for [%s] of [%d] ms\n", vfs_func
, 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
;
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
,
67 struct tevent_context
*ev
,
68 struct files_struct
*fsp
,
73 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
74 struct vfs_delay_inject_pread_state
*state
= NULL
;
76 struct timeval delay_tv
;
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
);
88 *state
= (struct vfs_delay_inject_pread_state
) {
98 subreq
= SMB_VFS_NEXT_PREAD_SEND(state
,
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
,
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
);
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
);
131 ok
= tevent_wakeup_recv(subreq
);
134 tevent_req_error(req
, EIO
);
138 subreq
= SMB_VFS_NEXT_PREAD_SEND(state
,
145 if (tevent_req_nomem(subreq
, req
)) {
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
);
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
)) {
174 *vfs_aio_state
= state
->vfs_aio_state
;
178 struct vfs_delay_inject_pwrite_state
{
179 struct tevent_context
*ev
;
180 struct vfs_handle_struct
*handle
;
181 struct files_struct
*fsp
;
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
,
195 struct tevent_context
*ev
,
196 struct files_struct
*fsp
,
201 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
202 struct vfs_delay_inject_pwrite_state
*state
= NULL
;
204 struct timeval delay_tv
;
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
);
216 *state
= (struct vfs_delay_inject_pwrite_state
) {
226 subreq
= SMB_VFS_NEXT_PWRITE_SEND(state
,
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
,
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
);
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
);
260 ok
= tevent_wakeup_recv(subreq
);
263 tevent_req_error(req
, EIO
);
267 subreq
= SMB_VFS_NEXT_PWRITE_SEND(state
,
274 if (tevent_req_nomem(subreq
, req
)) {
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
);
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
)) {
303 *vfs_aio_state
= state
->vfs_aio_state
;
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
,
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
);