From 9bf1c5c3e48ff905eec6f9ee469f1067b4105d42 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 18:22:38 +0200 Subject: vfs_delay_inject: add support for brl_[un]lock_windows() This demonstrates the two ways to handle the retry: - smb layer retry => plock->context.smblctx = UINT64_MAX - vfs backend retry => plock->context.smblctx = 0 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit c2503a5c68e967054ab84ca0d8ce693200c2e002) --- source3/modules/vfs_delay_inject.c | 117 +++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/source3/modules/vfs_delay_inject.c b/source3/modules/vfs_delay_inject.c index d561fadb03b..569bd40054a 100644 --- a/source3/modules/vfs_delay_inject.c +++ b/source3/modules/vfs_delay_inject.c @@ -304,12 +304,129 @@ static ssize_t vfs_delay_inject_pwrite_recv(struct tevent_req *req, return state->ret; } +struct vfs_delay_inject_brl_lock_state { + struct vfs_delay_inject_brl_lock_state *prev, *next; + struct files_struct *fsp; + struct GUID req_guid; + struct timeval delay_tv; + struct tevent_timer *delay_te; +}; + +static struct vfs_delay_inject_brl_lock_state *brl_lock_states; + +static int vfs_delay_inject_brl_lock_state_destructor(struct vfs_delay_inject_brl_lock_state *state) +{ + DLIST_REMOVE(brl_lock_states, state); + return 0; +} + +static void vfs_delay_inject_brl_lock_timer(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + struct vfs_delay_inject_brl_lock_state *state = + talloc_get_type_abort(private_data, + struct vfs_delay_inject_brl_lock_state); + NTSTATUS status; + + TALLOC_FREE(state->delay_te); + + status = share_mode_wakeup_waiters(state->fsp->file_id); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("share_mode_wakeup_waiters(%s) %s\n", + file_id_string_tos(&state->fsp->file_id), + nt_errstr(status)); + } +} + +static NTSTATUS vfs_delay_inject_brl_lock_windows(struct vfs_handle_struct *handle, + struct byte_range_lock *br_lck, + struct lock_struct *plock) +{ + struct files_struct *fsp = brl_fsp(br_lck); + TALLOC_CTX *req_mem_ctx = brl_req_mem_ctx(br_lck); + const struct GUID *req_guid = brl_req_guid(br_lck); + struct vfs_delay_inject_brl_lock_state *state = NULL; + bool expired; + + for (state = brl_lock_states; state != NULL; state = state->next) { + bool match; + + match = GUID_equal(&state->req_guid, req_guid); + if (match) { + break; + } + } + + if (state == NULL) { + int delay; + bool use_timer; + + state = talloc_zero(req_mem_ctx, + struct vfs_delay_inject_brl_lock_state); + if (state == NULL) { + return NT_STATUS_NO_MEMORY; + } + state->fsp = fsp; + state->req_guid = *req_guid; + + delay = lp_parm_int(SNUM(handle->conn), + "delay_inject", "brl_lock_windows", 0); + state->delay_tv = timeval_current_ofs_msec(delay); + + use_timer = lp_parm_bool(SNUM(handle->conn), + "delay_inject", "brl_lock_windows_use_timer", true); + + if (use_timer) { + state->delay_te = tevent_add_timer( + global_event_context(), + state, + state->delay_tv, + vfs_delay_inject_brl_lock_timer, + state); + if (state->delay_te == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + + talloc_set_destructor(state, + vfs_delay_inject_brl_lock_state_destructor); + DLIST_ADD_END(brl_lock_states, state); + } + + if (state->delay_te != NULL) { + plock->context.smblctx = 0; + return NT_STATUS_RETRY; + } + + expired = timeval_expired(&state->delay_tv); + if (!expired) { + plock->context.smblctx = UINT64_MAX; + return NT_STATUS_RETRY; + } + + TALLOC_FREE(state); + + return SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock); +} + +static bool vfs_delay_inject_brl_unlock_windows(struct vfs_handle_struct *handle, + struct byte_range_lock *br_lck, + const struct lock_struct *plock) +{ + return SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, br_lck, plock); +} + static struct vfs_fn_pointers vfs_delay_inject_fns = { .ntimes_fn = vfs_delay_inject_ntimes, .pread_send_fn = vfs_delay_inject_pread_send, .pread_recv_fn = vfs_delay_inject_pread_recv, .pwrite_send_fn = vfs_delay_inject_pwrite_send, .pwrite_recv_fn = vfs_delay_inject_pwrite_recv, + + .brl_lock_windows_fn = vfs_delay_inject_brl_lock_windows, + .brl_unlock_windows_fn = vfs_delay_inject_brl_unlock_windows, }; static_decl_vfs; -- cgit v1.2.1