]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs_delay_inject: add support for brl_[un]lock_windows()
authorStefan Metzmacher <metze@samba.org>
Mon, 19 Aug 2019 16:22:38 +0000 (18:22 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 9 Sep 2019 14:23:41 +0000 (14:23 +0000)
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 <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/modules/vfs_delay_inject.c

index d561fadb03be28f7936163eb52152e3761d52874..569bd40054a712cb8b33e89187b5a3d86b0b953d 100644 (file)
@@ -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;