smbd: Set SHARE_MODE_HAS_READ_LEASE when downgrading an oplock
[samba.git] / source3 / locking / locking.c
index cda1d9d82652510214818c4e9b4c1ed8e836f4f6..e173034165c9f6f5a11576df2f87333587b05f0d 100644 (file)
@@ -230,20 +230,64 @@ static void decrement_current_lock_count(files_struct *fsp,
  Utility function called by locking requests.
 ****************************************************************************/
 
-NTSTATUS do_lock(struct messaging_context *msg_ctx,
-                files_struct *fsp,
+struct do_lock_state {
+       struct files_struct *fsp;
+       uint64_t smblctx;
+       uint64_t count;
+       uint64_t offset;
+       enum brl_type lock_type;
+       enum brl_flavour lock_flav;
+
+       struct server_id blocker_pid;
+       uint64_t blocker_smblctx;
+       NTSTATUS status;
+};
+
+static void do_lock_fn(
+       struct db_record *rec,
+       bool *modified_dependent,
+       void *private_data)
+{
+       struct do_lock_state *state = private_data;
+       struct byte_range_lock *br_lck = NULL;
+
+       br_lck = brl_get_locks(talloc_tos(), state->fsp);
+       if (br_lck == NULL) {
+               state->status = NT_STATUS_NO_MEMORY;
+               return;
+       }
+
+       state->status = brl_lock(
+               br_lck,
+               state->smblctx,
+               messaging_server_id(state->fsp->conn->sconn->msg_ctx),
+               state->offset,
+               state->count,
+               state->lock_type,
+               state->lock_flav,
+               &state->blocker_pid,
+               &state->blocker_smblctx);
+
+       TALLOC_FREE(br_lck);
+}
+
+NTSTATUS do_lock(files_struct *fsp,
                 uint64_t smblctx,
                 uint64_t count,
                 uint64_t offset,
                 enum brl_type lock_type,
                 enum brl_flavour lock_flav,
-                bool blocking_lock,
                 struct server_id *pblocker_pid,
                 uint64_t *psmblctx)
 {
-       struct byte_range_lock *br_lck = NULL;
-       struct server_id blocker_pid = { 0 };
-       uint64_t blocker_smblctx = 0;
+       struct do_lock_state state = {
+               .fsp = fsp,
+               .smblctx = smblctx,
+               .count = count,
+               .offset = offset,
+               .lock_type = lock_type,
+               .lock_flav = lock_flav,
+       };
        NTSTATUS status;
 
        /* silently return ok on print files as we don't do locking there */
@@ -265,59 +309,44 @@ NTSTATUS do_lock(struct messaging_context *msg_ctx,
        /* NOTE! 0 byte long ranges ARE allowed and should be stored  */
 
        DBG_DEBUG("lock flavour %s lock type %s start=%"PRIu64" len=%"PRIu64" "
-                 "blocking_lock=%s requested for %s file %s\n",
+                 "requested for %s file %s\n",
                  lock_flav_name(lock_flav),
                  lock_type_name(lock_type),
                  offset,
                  count,
-                 blocking_lock ? "true" : "false",
                  fsp_fnum_dbg(fsp),
                  fsp_str_dbg(fsp));
 
-       br_lck = brl_get_locks(talloc_tos(), fsp);
-       if (!br_lck) {
-               return NT_STATUS_NO_MEMORY;
+       status = share_mode_do_locked(fsp->file_id, do_lock_fn, &state);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_DEBUG("share_mode_do_locked returned %s\n",
+                         nt_errstr(status));
+               return status;
        }
 
-       status = brl_lock(
-               msg_ctx,
-               br_lck,
-               smblctx,
-               messaging_server_id(fsp->conn->sconn->msg_ctx),
-               offset,
-               count,
-               lock_type,
-               lock_flav,
-               blocking_lock,
-               &blocker_pid,
-               &blocker_smblctx);
-
-       TALLOC_FREE(br_lck);
-
        if (psmblctx != NULL) {
-               *psmblctx = blocker_smblctx;
+               *psmblctx = state.blocker_smblctx;
        }
        if (pblocker_pid != NULL) {
-               *pblocker_pid = blocker_pid;
+               *pblocker_pid = state.blocker_pid;
        }
 
-       DBG_DEBUG("returning status=%s\n", nt_errstr(status));
+       DBG_DEBUG("returning status=%s\n", nt_errstr(state.status));
 
        increment_current_lock_count(fsp, lock_flav);
 
-       return status;
+       return state.status;
 }
 
 /****************************************************************************
  Utility function called by unlocking requests.
 ****************************************************************************/
 
-NTSTATUS do_unlock(struct messaging_context *msg_ctx,
-                       files_struct *fsp,
-                       uint64_t smblctx,
-                       uint64_t count,
-                       uint64_t offset,
-                       enum brl_flavour lock_flav)
+NTSTATUS do_unlock(files_struct *fsp,
+                  uint64_t smblctx,
+                  uint64_t count,
+                  uint64_t offset,
+                  enum brl_flavour lock_flav)
 {
        bool ok = False;
        struct byte_range_lock *br_lck = NULL;
@@ -342,8 +371,7 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
-       ok = brl_unlock(msg_ctx,
-                       br_lck,
+       ok = brl_unlock(br_lck,
                        smblctx,
                        messaging_server_id(fsp->conn->sconn->msg_ctx),
                        offset,
@@ -365,8 +393,7 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx,
  Remove any locks on this fd. Called from file_close().
 ****************************************************************************/
 
-void locking_close_file(struct messaging_context *msg_ctx,
-                       files_struct *fsp,
+void locking_close_file(files_struct *fsp,
                        enum file_close_type close_type)
 {
        struct byte_range_lock *br_lck;
@@ -392,7 +419,7 @@ void locking_close_file(struct messaging_context *msg_ctx,
                 * implictly, we're closing the file and thus remove a
                 * share mode. This will wake the waiters.
                 */
-               brl_close_fnum(msg_ctx, br_lck);
+               brl_close_fnum(br_lck);
                TALLOC_FREE(br_lck);
        }
 }
@@ -920,6 +947,7 @@ bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
        }
 
        e->op_type = LEVEL_II_OPLOCK;
+       lck->data->flags |= SHARE_MODE_HAS_READ_LEASE;
        lck->data->modified = True;
        return True;
 }