From: Ralph Boehme Date: Tue, 28 Jan 2025 10:19:05 +0000 (+0100) Subject: smbd: use share_mode_do_locked_brl() in vfs_default_durable_disconnect() X-Git-Tag: samba-4.22.1~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dd4037fcb1a77d6ea05265079967016afb1c8364;p=thirdparty%2Fsamba.git smbd: use share_mode_do_locked_brl() in vfs_default_durable_disconnect() BUG: https://bugzilla.samba.org/show_bug.cgi?id=15767 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (backported from commit 393379fc9c726eb781fd1bfb3a70ea2802739aff) [slow@samba.org: conflict due to removed delayed write time handling] --- diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index 92621c41577..4dcae87691b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -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; } diff --git a/source3/locking/proto.h b/source3/locking/proto.h index 418799a1855..c7ee6d1beab 100644 --- a/source3/locking/proto.h +++ b/source3/locking/proto.h @@ -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, diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c index 91d6de20f5b..2a602183ba7 100644 --- a/source3/smbd/durable.c +++ b/source3/smbd/durable.c @@ -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)) {