From: Stefan Metzmacher Date: Mon, 15 Aug 2022 15:42:33 +0000 (+0200) Subject: s3:smbd: maintain all SHARE_MODE_LEASE_* flags not only _READ X-Git-Tag: talloc-2.4.0~835 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a4dd4d5f0fdb8cb242dde93cf620f238fccf9e9c;p=thirdparty%2Fsamba.git s3:smbd: maintain all SHARE_MODE_LEASE_* flags not only _READ Remember SMB2 Create is the only was to upgrade a lease. The strategy is that opening of a file will always result in storing the total lease bits. But we're lazy clearing the flags on close. We'll only clear them by traversing all entries when we break a NONE or when opening a new handle. We don't do any decision on SHARE_MODE_LEASE_{HANDLE,WRITE}, maybe we'll do in future, but at least it should be much more sane for debugging now! BUG: https://bugzilla.samba.org/show_bug.cgi?id=15125 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison --- diff --git a/source3/smbd/open.c b/source3/smbd/open.c index cb54f03a3b8..3dc8c60e763 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2571,6 +2571,7 @@ struct delay_for_oplock_state { bool got_handle_lease; bool got_oplock; bool have_other_lease; + uint32_t total_lease_types; bool delay; }; @@ -2648,6 +2649,12 @@ static bool delay_for_oplock_fn( e_lease_type = get_lease_type(e, fsp->file_id); } + if (((e_lease_type & ~state->total_lease_types) != 0) && + !share_entry_stale_pid(e)) + { + state->total_lease_types |= e_lease_type; + } + if (!state->got_handle_lease && ((e_lease_type & SMB2_LEASE_HANDLE) != 0) && !share_entry_stale_pid(e)) { @@ -2770,6 +2777,8 @@ static NTSTATUS delay_for_oplock(files_struct *fsp, oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); } + share_mode_flags_get(lck, NULL, NULL, &state.total_lease_types); + if (is_oplock_stat_open(fsp->access_mask)) { goto grant; } @@ -2788,6 +2797,7 @@ static NTSTATUS delay_for_oplock(files_struct *fsp, break; } + state.total_lease_types = SMB2_LEASE_NONE; ok = share_mode_forall_entries(lck, delay_for_oplock_fn, &state); if (!ok) { return NT_STATUS_INTERNAL_ERROR; @@ -2865,15 +2875,17 @@ grant: granted = map_oplock_to_lease_type(oplock_type); } - if (granted & SMB2_LEASE_READ) { + state.total_lease_types |= granted; + + { uint32_t acc, sh, ls; share_mode_flags_get(lck, &acc, &sh, &ls); - ls |= SMB2_LEASE_READ; + ls = state.total_lease_types; share_mode_flags_set(lck, acc, sh, ls, NULL); } DBG_DEBUG("oplock type 0x%x granted (%s%s%s)(0x%x), on file %s, " - "requested 0x%x (%s%s%s)(0x%x)\n", + "requested 0x%x (%s%s%s)(0x%x) => total (%s%s%s)(0x%x)\n", fsp->oplock_type, granted & SMB2_LEASE_READ ? "R":"", granted & SMB2_LEASE_WRITE ? "W":"", @@ -2884,7 +2896,11 @@ grant: requested & SMB2_LEASE_READ ? "R":"", requested & SMB2_LEASE_WRITE ? "W":"", requested & SMB2_LEASE_HANDLE ? "H":"", - requested); + requested, + state.total_lease_types & SMB2_LEASE_READ ? "R":"", + state.total_lease_types & SMB2_LEASE_WRITE ? "W":"", + state.total_lease_types & SMB2_LEASE_HANDLE ? "H":"", + state.total_lease_types); *poplock_type = oplock_type; *pgranted = granted; diff --git a/source3/smbd/smb2_oplock.c b/source3/smbd/smb2_oplock.c index c4f4fb3ac33..a7bf803e878 100644 --- a/source3/smbd/smb2_oplock.c +++ b/source3/smbd/smb2_oplock.c @@ -1150,6 +1150,7 @@ struct break_to_none_state { struct smb2_lease_key lease_key; struct GUID client_guid; size_t num_read_leases; + uint32_t total_lease_types; }; static bool do_break_lease_to_none(struct share_mode_entry *e, @@ -1179,6 +1180,8 @@ static bool do_break_lease_to_none(struct share_mode_entry *e, return false; } + state->total_lease_types |= current_state; + if ((current_state & SMB2_LEASE_READ) == 0) { return false; } @@ -1229,6 +1232,8 @@ static bool do_break_oplock_to_none(struct share_mode_entry *e, DBG_DEBUG("e->op_type == %d\n", e->op_type); + state->total_lease_types |= map_oplock_to_lease_type(e->op_type); + if (e->op_type == NO_OPLOCK) { return false; } @@ -1313,14 +1318,14 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp, DBG_WARNING("share_mode_forall_entries failed\n"); } - if (state.num_read_leases == 0) { + { /* - * Lazy update here. It might be that the read lease - * has gone in the meantime. + * Lazy update here. It might be that all leases + * have gone in the meantime. */ uint32_t acc, sh, ls; share_mode_flags_get(lck, &acc, &sh, &ls); - ls &= ~SMB2_LEASE_READ; + ls = state.total_lease_types; share_mode_flags_set(lck, acc, sh, ls, NULL); }