smbd: Ping dbwrap_watch on locking.tdb for in smbd_do_unlocking()
authorVolker Lendecke <vl@samba.org>
Thu, 13 Jun 2019 10:58:02 +0000 (03:58 -0700)
committerJeremy Allison <jra@samba.org>
Thu, 20 Jun 2019 17:18:19 +0000 (17:18 +0000)
smbd_smb1_do_locks_send() watches the file's locking.tdb record for
changes, like the oplock code does. Unlocking a byte range thus must
trigger a retry.

With the share mode cache get_existing_share_mode_lock() is pretty
cheap. We have to write out the share mode record with the current
code, but an obvious optimization will be a share_mode_do_locked doing
all this without actually unmarshalling the locking.tdb entry. And --
there's precedence for this pattern in downgrade_lease()...

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/reply.c

index d02f14ead13f959ab0438f9de0e68a656d275422..0dded28a06531c02ef38b0b9aaee698ecc4c0980 100644 (file)
@@ -44,6 +44,7 @@
 #include "lib/tevent_wait.h"
 #include "libcli/smb/smb_signing.h"
 #include "lib/util/sys_rw_data.h"
+#include "librpc/gen_ndr/open_files.h"
 
 /****************************************************************************
  Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
@@ -8226,11 +8227,14 @@ NTSTATUS smbd_do_unlocking(struct smb_request *req,
                           struct smbd_lock_element *ulocks,
                           enum brl_flavour lock_flav)
 {
+       struct share_mode_lock *lck;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        uint16_t i;
 
+       lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
+
        for(i = 0; i < num_ulocks; i++) {
                struct smbd_lock_element *e = &ulocks[i];
-               NTSTATUS status;
 
                DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
                          "pid %"PRIu64", file %s\n",
@@ -8241,7 +8245,8 @@ NTSTATUS smbd_do_unlocking(struct smb_request *req,
 
                if (e->brltype != UNLOCK_LOCK) {
                        /* this can only happen with SMB2 */
-                       return NT_STATUS_INVALID_PARAMETER;
+                       status = NT_STATUS_INVALID_PARAMETER;
+                       goto done;
                }
 
                status = do_unlock(req->sconn->msg_ctx,
@@ -8255,20 +8260,28 @@ NTSTATUS smbd_do_unlocking(struct smb_request *req,
                           nt_errstr(status)));
 
                if (!NT_STATUS_IS_OK(status)) {
-                       return status;
+                       goto done;
                }
        }
 
        DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
                  num_ulocks));
 
-       return NT_STATUS_OK;
+done:
+       if (NT_STATUS_IS_OK(status) && (lck != NULL)) {
+               lck->data->modified = true;
+       }
+
+       TALLOC_FREE(lck);
+       return status;
 }
 
 /****************************************************************************
  Reply to a lockingX request.
 ****************************************************************************/
 
+static void reply_lockingx_done(struct tevent_req *subreq);
+
 void reply_lockingX(struct smb_request *req)
 {
        connection_struct *conn = req->conn;