From 393379fc9c726eb781fd1bfb3a70ea2802739aff Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 28 Jan 2025 11:19:05 +0100 Subject: [PATCH] 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 --- source3/locking/brlock.c | 14 ++------ source3/locking/proto.h | 9 +++++- source3/smbd/durable.c | 69 ++++++++++++++++++++++++++++------------ 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index d73a81d4b80..35299a49858 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1370,14 +1370,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; @@ -1393,11 +1393,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]; @@ -1407,22 +1402,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; } @@ -1432,7 +1423,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 d63c2828b0c..5ecb12b4253 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 737ff5dfe2e..a8a96cacdab 100644 --- a/source3/smbd/durable.c +++ b/source3/smbd/durable.c @@ -127,6 +127,38 @@ 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; + bool ok; + + 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, @@ -137,8 +169,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; @@ -192,27 +223,23 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp, return NT_STATUS_NOT_SUPPORTED; } - /* - * 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) { - 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); - } + state = (struct durable_disconnect_state) { + .fsp = fsp, + }; + + 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)) { -- 2.47.3