From b56bb2ac59dd190cdf3c726a7becf2ae9d296657 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 19 Aug 2019 12:04:43 +0200 Subject: s3:blocking: maintain state->deny_status For Windows locks we start with LOCK_NOT_GRANTED and use FILE_LOCK_CONFLICT if we retried after a timeout. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14113 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit aba0ee46258f3dd910421facb742fce3318a6946) --- selftest/knownfail.d/samba3posixtimedlock | 1 - source3/smbd/blocking.c | 33 ++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) delete mode 100644 selftest/knownfail.d/samba3posixtimedlock diff --git a/selftest/knownfail.d/samba3posixtimedlock b/selftest/knownfail.d/samba3posixtimedlock deleted file mode 100644 index 56d2d349e1e..00000000000 --- a/selftest/knownfail.d/samba3posixtimedlock +++ /dev/null @@ -1 +0,0 @@ -^samba3.raw.samba3posixtimedlock.samba3posixtimedlock diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 50e1d436eb7..a87d62d910a 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -109,6 +109,7 @@ struct smbd_smb1_do_locks_state { uint16_t num_locks; struct smbd_lock_element *locks; uint16_t blocker; + NTSTATUS deny_status; }; static void smbd_smb1_do_locks_try(struct tevent_req *req); @@ -176,6 +177,16 @@ struct tevent_req *smbd_smb1_do_locks_send( state->num_locks = num_locks; state->locks = locks; + if (lock_flav == POSIX_LOCK) { + /* + * SMB1 posix locks always use + * NT_STATUS_FILE_LOCK_CONFLICT. + */ + state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; + } else { + state->deny_status = NT_STATUS_LOCK_NOT_GRANTED; + } + DBG_DEBUG("state=%p, state->smbreq=%p\n", state, state->smbreq); if (num_locks == 0) { @@ -245,10 +256,19 @@ struct tevent_req *smbd_smb1_do_locks_send( state->timeout, blocking_smblctx); + /* + * If the endtime is not elapsed yet, + * it means we'll retry after a timeout. + * In that case we'll have to return + * NT_STATUS_FILE_LOCK_CONFLICT + * instead of NT_STATUS_LOCK_NOT_GRANTED. + */ if (state->timeout == 0) { + status = state->deny_status; tevent_req_nterror(req, status); goto done; } + state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; subreq = dbwrap_watched_watch_send( state, state->ev, lck->data->record, blocking_pid); @@ -379,16 +399,19 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req) * Otherwise keep waiting either waiting * for changes in locking.tdb or the polling * mode timers waiting for posix locks. + * + * If the endtime is not expired yet, + * it means we'll retry after a timeout. + * In that case we'll have to return + * NT_STATUS_FILE_LOCK_CONFLICT + * instead of NT_STATUS_LOCK_NOT_GRANTED. */ elapsed = timeval_elapsed(&state->endtime); if (elapsed > 0) { - /* - * On timeout we always return - * NT_STATUS_FILE_LOCK_CONFLICT - */ - status = NT_STATUS_FILE_LOCK_CONFLICT; + status = state->deny_status; goto done; } + state->deny_status = NT_STATUS_FILE_LOCK_CONFLICT; subreq = dbwrap_watched_watch_send( state, state->ev, lck->data->record, blocking_pid); -- cgit v1.2.1