]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: use share_mode_do_locked_brl() in vfs_default_durable_disconnect()
authorRalph Boehme <slow@samba.org>
Tue, 28 Jan 2025 10:19:05 +0000 (11:19 +0100)
committerJule Anger <janger@samba.org>
Thu, 17 Apr 2025 11:16:13 +0000 (11:16 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15767

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(backported from commit 393379fc9c726eb781fd1bfb3a70ea2802739aff)
[slow@samba.org: conflict due to removed delayed write time handling]

source3/locking/brlock.c
source3/locking/proto.h
source3/smbd/durable.c

index 92621c4157781f47d33444d7f596e25ad1dabe68..4dcae87691bfd6fff04b227c92d20ae576ded221 100644 (file)
@@ -1368,14 +1368,14 @@ void brl_close_fnum(struct byte_range_lock *br_lck)
        }
 }
 
-bool brl_mark_disconnected(struct files_struct *fsp)
+bool brl_mark_disconnected(struct files_struct *fsp,
+                          struct byte_range_lock *br_lck)
 {
        uint32_t tid = fsp->conn->cnum;
        uint64_t smblctx;
        uint64_t fnum = fsp->fnum;
        unsigned int i;
        struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
-       struct byte_range_lock *br_lck = NULL;
 
        if (fsp->op == NULL) {
                return false;
@@ -1391,11 +1391,6 @@ bool brl_mark_disconnected(struct files_struct *fsp)
                return true;
        }
 
-       br_lck = brl_get_locks(talloc_tos(), fsp);
-       if (br_lck == NULL) {
-               return false;
-       }
-
        for (i=0; i < br_lck->num_locks; i++) {
                struct lock_struct *lock = &br_lck->lock_data[i];
 
@@ -1405,22 +1400,18 @@ bool brl_mark_disconnected(struct files_struct *fsp)
                 */
 
                if (lock->context.smblctx != smblctx) {
-                       TALLOC_FREE(br_lck);
                        return false;
                }
 
                if (lock->context.tid != tid) {
-                       TALLOC_FREE(br_lck);
                        return false;
                }
 
                if (!server_id_equal(&lock->context.pid, &self)) {
-                       TALLOC_FREE(br_lck);
                        return false;
                }
 
                if (lock->fnum != fnum) {
-                       TALLOC_FREE(br_lck);
                        return false;
                }
 
@@ -1430,7 +1421,6 @@ bool brl_mark_disconnected(struct files_struct *fsp)
        }
 
        br_lck->modified = true;
-       TALLOC_FREE(br_lck);
        return true;
 }
 
index 44808171f1a3130b4c61f66b58423bd0f1ed1a4a..d3b4e02bc26ed6f20daf30205e505ca2e2b983ae 100644 (file)
@@ -75,7 +75,14 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck,
                br_off *psize,
                enum brl_type *plock_type,
                enum brl_flavour lock_flav);
-bool brl_mark_disconnected(struct files_struct *fsp);
+
+struct brl_connectstate {
+       bool ok;
+       struct files_struct *fsp;
+};
+
+bool brl_mark_disconnected(struct files_struct *fsp,
+                          struct byte_range_lock *br_lck);
 bool brl_reconnect_disconnected(struct files_struct *fsp);
 void brl_close_fnum(struct byte_range_lock *br_lck);
 int brl_forall(void (*fn)(struct file_id id, struct server_id pid,
index bd0c9f58e2408bcb2a3947d62b7f12896a98810e..d315cb21ccce0e0c86a227a0a21f519e11d8ff81 100644 (file)
@@ -133,6 +133,63 @@ NTSTATUS vfs_default_durable_cookie(struct files_struct *fsp,
        return NT_STATUS_OK;
 }
 
+struct durable_disconnect_state {
+       NTSTATUS status;
+       struct files_struct *fsp;
+};
+
+static void default_durable_disconnect_fn(struct share_mode_lock *lck,
+                                         struct byte_range_lock *br_lck,
+                                         void *private_data)
+{
+       struct durable_disconnect_state *state = private_data;
+       struct files_struct *fsp = state->fsp;
+       struct smb_file_time ft;
+       bool ok;
+
+       /* Ensure any pending write time updates are done. */
+       if (fsp->update_write_time_event) {
+               fsp_flush_write_time_update(fsp);
+       }
+
+
+       init_smb_file_time(&ft);
+
+       if (fsp->fsp_flags.write_time_forced) {
+               NTTIME mtime = share_mode_changed_write_time(lck);
+               ft.mtime = nt_time_to_full_timespec(mtime);
+       } else if (fsp->fsp_flags.update_write_time_on_close) {
+               if (is_omit_timespec(&fsp->close_write_time)) {
+                       ft.mtime = timespec_current();
+               } else {
+                       ft.mtime = fsp->close_write_time;
+               }
+       }
+
+       if (!is_omit_timespec(&ft.mtime)) {
+               round_timespec(fsp->conn->ts_res, &ft.mtime);
+               file_ntimes(fsp->conn, fsp, &ft);
+       }
+
+       ok = mark_share_mode_disconnected(lck, fsp);
+       if (!ok) {
+               state->status = NT_STATUS_UNSUCCESSFUL;
+               return;
+       }
+
+       if (br_lck == NULL) {
+               state->status = NT_STATUS_OK;
+               return;
+       }
+
+       ok = brl_mark_disconnected(fsp, br_lck);
+       if (!ok) {
+               state->status = NT_STATUS_UNSUCCESSFUL;
+               return;
+       }
+       state->status = NT_STATUS_OK;
+}
+
 NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
                                        const DATA_BLOB old_cookie,
                                        TALLOC_CTX *mem_ctx,
@@ -143,8 +200,7 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
        enum ndr_err_code ndr_err;
        struct vfs_default_durable_cookie cookie;
        DATA_BLOB new_cookie_blob = data_blob_null;
-       struct share_mode_lock *lck;
-       bool ok;
+       struct durable_disconnect_state state;
 
        *new_cookie = data_blob_null;
 
@@ -198,52 +254,23 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
                return NT_STATUS_NOT_SUPPORTED;
        }
 
-       /* Ensure any pending write time updates are done. */
-       if (fsp->update_write_time_event) {
-               fsp_flush_write_time_update(fsp);
-       }
+       state = (struct durable_disconnect_state) {
+               .fsp = fsp,
+       };
 
-       /*
-        * The above checks are done in mark_share_mode_disconnected() too
-        * but we want to avoid getting the lock if possible
-        */
-       lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
-       if (lck != NULL) {
-               struct smb_file_time ft;
-
-               init_smb_file_time(&ft);
-
-               if (fsp->fsp_flags.write_time_forced) {
-                       NTTIME mtime = share_mode_changed_write_time(lck);
-                       ft.mtime = nt_time_to_full_timespec(mtime);
-               } else if (fsp->fsp_flags.update_write_time_on_close) {
-                       if (is_omit_timespec(&fsp->close_write_time)) {
-                               ft.mtime = timespec_current();
-                       } else {
-                               ft.mtime = fsp->close_write_time;
-                       }
-               }
-
-               if (!is_omit_timespec(&ft.mtime)) {
-                       round_timespec(conn->ts_res, &ft.mtime);
-                       file_ntimes(conn, fsp, &ft);
-               }
-
-               ok = mark_share_mode_disconnected(lck, fsp);
-               if (!ok) {
-                       TALLOC_FREE(lck);
-               }
-       }
-       if (lck != NULL) {
-               ok = brl_mark_disconnected(fsp);
-               if (!ok) {
-                       TALLOC_FREE(lck);
-               }
+       status = share_mode_do_locked_brl(fsp,
+                                         default_durable_disconnect_fn,
+                                         &state);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("share_mode_do_locked_brl [%s] failed: %s\n",
+                       fsp_str_dbg(fsp), nt_errstr(status));
+               return status;
        }
-       if (lck == NULL) {
-               return NT_STATUS_NOT_SUPPORTED;
+       if (!NT_STATUS_IS_OK(state.status)) {
+               DBG_ERR("default_durable_disconnect_fn [%s] failed: %s\n",
+                       fsp_str_dbg(fsp), nt_errstr(state.status));
+               return state.status;
        }
-       TALLOC_FREE(lck);
 
        status = vfs_stat_fsp(fsp);
        if (!NT_STATUS_IS_OK(status)) {