s3:blocking: fix posix lock retry
authorStefan Metzmacher <metze@samba.org>
Thu, 15 Aug 2019 12:21:38 +0000 (14:21 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 9 Sep 2019 14:23:39 +0000 (14:23 +0000)
We should evaluate the timeout condition after the very last
retry and not before.

Otherwise we'd fail to retry when waiting for posix locks.
The problem happens if the client provided timeout is smaller
than the 1 sec (for testing temporary 15 secs) retry.

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/lock9 [deleted file]
source3/smbd/blocking.c

diff --git a/selftest/knownfail.d/lock9 b/selftest/knownfail.d/lock9
deleted file mode 100644 (file)
index 0446225..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.smbtorture_s3.*.LOCK9B
index 81facc43154d5e465cd617d6d163ac77fde29ab9..587923aa5ec18754356370b1c10a0dfa3fe6af67 100644 (file)
@@ -319,6 +319,7 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req)
        struct tevent_req *subreq = NULL;
        NTSTATUS status;
        bool ok;
+       double elapsed;
 
        lck = get_existing_share_mode_lock(state, fsp->file_id);
        if (tevent_req_nomem(lck, req)) {
@@ -341,6 +342,24 @@ static void smbd_smb1_do_locks_try(struct tevent_req *req)
                goto done;
        }
 
+       /*
+        * The client specified timeout elapsed
+        * avoid further retries.
+        *
+        * Otherwise keep waiting either waiting
+        * for changes in locking.tdb or the polling
+        * mode timers waiting for posix locks.
+        */
+       elapsed = timeval_elapsed(&state->endtime);
+       if (elapsed > 0) {
+               /*
+                * On timeout we always return
+                * NT_STATUS_FILE_LOCK_CONFLICT
+                */
+               status = NT_STATUS_FILE_LOCK_CONFLICT;
+               goto done;
+       }
+
        subreq = dbwrap_watched_watch_send(
                state, state->ev, lck->data->record, blocking_pid);
        if (tevent_req_nomem(subreq, req)) {
@@ -395,17 +414,12 @@ static void smbd_smb1_do_locks_retry(struct tevent_req *subreq)
        DBG_DEBUG("dbwrap_watched_watch_recv returned %s\n",
                  nt_errstr(status));
 
-       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
-               double elapsed = timeval_elapsed(&state->endtime);
-               if (elapsed > 0) {
-                       smbd_smb1_brl_finish_by_req(
-                               req, NT_STATUS_FILE_LOCK_CONFLICT);
-                       return;
-               }
-               /*
-                * This is a posix lock retry. Just retry.
-                */
-       }
+       /*
+        * We ignore any errors here, it's most likely
+        * we just get NT_STATUS_OK or NT_STATUS_IO_TIMEOUT.
+        *
+        * In any case we can just give it a retry.
+        */
 
        smbd_smb1_do_locks_try(req);
 }