summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2019-08-19 18:22:38 +0200
committerStefan Metzmacher <metze@samba.org>2019-09-09 16:04:31 +0000
commit9bf1c5c3e48ff905eec6f9ee469f1067b4105d42 (patch)
tree9a8cd82e06f2d199981da9c55ebbb5c10cd4e2aa
parentec21e68912d2c9b1f4c3aa57d9b34db038a6b66c (diff)
downloadsamba-9bf1c5c3e48ff905eec6f9ee469f1067b4105d42.tar.gz
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 <metze@samba.org> Reviewed-by: Volker Lendecke <vl@samba.org> (cherry picked from commit c2503a5c68e967054ab84ca0d8ce693200c2e002)
-rw-r--r--source3/modules/vfs_delay_inject.c117
1 files changed, 117 insertions, 0 deletions
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;