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 struct vfs_delay_inject_brl_lock_state
{
308 struct vfs_delay_inject_brl_lock_state
*prev
, *next
;
309 struct files_struct
*fsp
;
310 struct GUID req_guid
;
311 struct timeval delay_tv
;
312 struct tevent_timer
*delay_te
;
315 static struct vfs_delay_inject_brl_lock_state
*brl_lock_states
;
317 static int vfs_delay_inject_brl_lock_state_destructor(struct vfs_delay_inject_brl_lock_state
*state
)
319 DLIST_REMOVE(brl_lock_states
, state
);
323 static void vfs_delay_inject_brl_lock_timer(struct tevent_context
*ev
,
324 struct tevent_timer
*te
,
325 struct timeval current_time
,
328 struct vfs_delay_inject_brl_lock_state
*state
=
329 talloc_get_type_abort(private_data
,
330 struct vfs_delay_inject_brl_lock_state
);
333 TALLOC_FREE(state
->delay_te
);
335 status
= share_mode_wakeup_waiters(state
->fsp
->file_id
);
336 if (!NT_STATUS_IS_OK(status
)) {
337 struct file_id_buf idbuf
;
338 DBG_ERR("share_mode_wakeup_waiters(%s) %s\n",
339 file_id_str_buf(state
->fsp
->file_id
, &idbuf
),
344 static NTSTATUS
vfs_delay_inject_brl_lock_windows(struct vfs_handle_struct
*handle
,
345 struct byte_range_lock
*br_lck
,
346 struct lock_struct
*plock
)
348 struct files_struct
*fsp
= brl_fsp(br_lck
);
349 TALLOC_CTX
*req_mem_ctx
= brl_req_mem_ctx(br_lck
);
350 const struct GUID
*req_guid
= brl_req_guid(br_lck
);
351 struct vfs_delay_inject_brl_lock_state
*state
= NULL
;
354 for (state
= brl_lock_states
; state
!= NULL
; state
= state
->next
) {
357 match
= GUID_equal(&state
->req_guid
, req_guid
);
367 state
= talloc_zero(req_mem_ctx
,
368 struct vfs_delay_inject_brl_lock_state
);
370 return NT_STATUS_NO_MEMORY
;
373 state
->req_guid
= *req_guid
;
375 delay
= lp_parm_int(SNUM(handle
->conn
),
376 "delay_inject", "brl_lock_windows", 0);
377 state
->delay_tv
= timeval_current_ofs_msec(delay
);
379 use_timer
= lp_parm_bool(SNUM(handle
->conn
),
380 "delay_inject", "brl_lock_windows_use_timer", true);
383 state
->delay_te
= tevent_add_timer(
384 global_event_context(),
387 vfs_delay_inject_brl_lock_timer
,
389 if (state
->delay_te
== NULL
) {
390 return NT_STATUS_NO_MEMORY
;
394 talloc_set_destructor(state
,
395 vfs_delay_inject_brl_lock_state_destructor
);
396 DLIST_ADD_END(brl_lock_states
, state
);
399 if (state
->delay_te
!= NULL
) {
400 plock
->context
.smblctx
= 0;
401 return NT_STATUS_RETRY
;
404 expired
= timeval_expired(&state
->delay_tv
);
406 plock
->context
.smblctx
= UINT64_MAX
;
407 return NT_STATUS_RETRY
;
412 return SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle
, br_lck
, plock
);
415 static bool vfs_delay_inject_brl_unlock_windows(struct vfs_handle_struct
*handle
,
416 struct byte_range_lock
*br_lck
,
417 const struct lock_struct
*plock
)
419 return SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle
, br_lck
, plock
);
422 static struct vfs_fn_pointers vfs_delay_inject_fns
= {
423 .ntimes_fn
= vfs_delay_inject_ntimes
,
424 .pread_send_fn
= vfs_delay_inject_pread_send
,
425 .pread_recv_fn
= vfs_delay_inject_pread_recv
,
426 .pwrite_send_fn
= vfs_delay_inject_pwrite_send
,
427 .pwrite_recv_fn
= vfs_delay_inject_pwrite_recv
,
429 .brl_lock_windows_fn
= vfs_delay_inject_brl_lock_windows
,
430 .brl_unlock_windows_fn
= vfs_delay_inject_brl_unlock_windows
,
434 NTSTATUS
vfs_delay_inject_init(TALLOC_CTX
*ctx
)
436 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION
, "delay_inject",
437 &vfs_delay_inject_fns
);