s3:blocking: maintain state->deny_status
authorStefan Metzmacher <metze@samba.org>
Mon, 19 Aug 2019 10:04:43 +0000 (12:04 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 9 Sep 2019 14:23:40 +0000 (14:23 +0000)
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 <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
selftest/knownfail.d/samba3posixtimedlock [deleted file]
source3/smbd/blocking.c

diff --git a/selftest/knownfail.d/samba3posixtimedlock b/selftest/knownfail.d/samba3posixtimedlock
deleted file mode 100644 (file)
index 56d2d34..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.raw.samba3posixtimedlock.samba3posixtimedlock
index 50e1d436eb75c30d554fe0ca997e5f65b79c5ca6..a87d62d910aaa60e6fec9acabe5be32f86be241f 100644 (file)
@@ -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);