[SCM] Samba Shared Repository - branch master updated
Stefan Metzmacher
metze at samba.org
Thu Oct 10 14:00:02 UTC 2024
The branch, master has been updated
via dd5b9e08c7a s3:smbd: avoid false positives for got_oplock and have_other_lease in delay_for_oplock_fn
via b1e5f5d8d28 s3:smbd: allow reset_share_mode_entry() to handle more than one durable handle
via 2869bd1a507 s3:smbd: let durable_reconnect_fn already check for a disconnected handle with the correct file_id
via 9e98cd5c7a1 s4:torture/smb2: add smb2.durable-v2-open.{keep,purge}-disconnected-* tests
via 77c7741f39a s4:torture/smb2: add smb2.durable-v2-open.{[non]stat[RH]-and,two-same,two-different}-lease
via 0893ae88180 s3:smbd: only store durable handles with byte range locks when having WRITE lease
via 8884d617310 s4:torture/smb2: add smb2.durable-v2-open.lock-{oplock,lease,noW-lease}
via 1cc1586d84a s4:torture/smb2: add smb2.durable-open.lock-noW-lease
via 9b2417c2f04 s4:torture/smb2: improve error handling in durable_v2_open.c
via e65e1326a02 s4:torture/smb2: improve error handling in durable_open.c
from 9ad287ed9c4 ctdb-build: Add missing ctdb-tcp dependency
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit dd5b9e08c7a98c54b62d3b097c75faa09cd17da7
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 30 14:16:12 2024 +0200
s3:smbd: avoid false positives for got_oplock and have_other_lease in delay_for_oplock_fn
stat opens should not cause a oplock/lease downgrade if
they don't have a lease attached to itself.
Note that opens broken to NONE still count if they are
non-stat opens...
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
Autobuild-Date(master): Thu Oct 10 13:59:18 UTC 2024 on atb-devel-224
commit b1e5f5d8d2852b66ca4c858d14d367ffe228a88d
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu Aug 29 18:43:14 2024 +0200
s3:smbd: allow reset_share_mode_entry() to handle more than one durable handle
This means that multiple durable handles with RH leases can
co-exist now... Before only the last remaining durable handle
was able to pass the SMB_VFS_DURABLE_DISCONNECT() step.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 2869bd1a507e7376f0bb0ec68ed4e045b043cfdb
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu Aug 29 20:20:23 2024 +0200
s3:smbd: let durable_reconnect_fn already check for a disconnected handle with the correct file_id
We'll soon allow more than one disconnected durable handle, so
we need to find the correct one instead of assuming only a single
one.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 9e98cd5c7a180521026b0d73a330bdaf2c8af73a
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Sep 4 18:18:43 2024 +0200
s4:torture/smb2: add smb2.durable-v2-open.{keep,purge}-disconnected-* tests
These demonstrate which durables handles are kept and which are purged
because of various opens, writes or renames.
smb2.durable-v2-open.keep-disconnected-rh-with-stat-open
smb2.durable-v2-open.keep-disconnected-rh-with-rh-open
smb2.durable-v2-open.keep-disconnected-rh-with-rwh-open
smb2.durable-v2-open.keep-disconnected-rwh-with-stat-open
smb2.durable-v2-open.purge-disconnected-rwh-with-rwh-open
smb2.durable-v2-open.purge-disconnected-rwh-with-rh-open
smb2.durable-v2-open.purge-disconnected-rh-with-share-none-open
smb2.durable-v2-open.purge-disconnected-rh-with-write
smb2.durable-v2-open.purge-disconnected-rh-with-rename
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15708
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 77c7741f39a0a9789bede7c4722bd3f35d4af3fd
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Aug 28 16:48:27 2024 +0200
s4:torture/smb2: add smb2.durable-v2-open.{[non]stat[RH]-and,two-same,two-different}-lease
These show that it's possible to have durable handles in addition
of stat opens, as well as multiple durable opens with RH leases.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 0893ae88180137d44f17196234f657d362543ff5
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 30 18:10:16 2024 +0200
s3:smbd: only store durable handles with byte range locks when having WRITE lease
This simplifies the reconnect assumptions, when we want to allow
more than one durable handle on a file for multiple clients with
READ+HANDLE leases.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 8884d617310b47375e38c0386433c5e183703454
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 30 17:38:02 2024 +0200
s4:torture/smb2: add smb2.durable-v2-open.lock-{oplock,lease,noW-lease}
This demonstrates that a W lease is required for a
durable handle to be durable when it has byte range locks.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 1cc1586d84a65046ab7804f17297c6964bb76c23
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 30 17:38:02 2024 +0200
s4:torture/smb2: add smb2.durable-open.lock-noW-lease
This demonstrates that a W lease is required for a
durable handle to be durable when it has byte range locks.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit 9b2417c2f04857709c25e3665cd783a68edf0cf2
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 30 14:22:24 2024 +0200
s4:torture/smb2: improve error handling in durable_v2_open.c
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
commit e65e1326a0214a7dfff75ea1e528e82c8fc64517
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 30 14:22:24 2024 +0200
s4:torture/smb2: improve error handling in durable_open.c
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15649
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15651
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
-----------------------------------------------------------------------
Summary of changes:
selftest/knownfail | 1 -
selftest/knownfail.d/smb2.durable-v2-open.bug15708 | 7 +
source3/locking/share_mode_lock.c | 315 ++-
source3/smbd/durable.c | 35 +-
source3/smbd/open.c | 26 +-
source4/torture/smb2/durable_open.c | 136 +-
source4/torture/smb2/durable_v2_open.c | 2990 +++++++++++++++++++-
7 files changed, 3430 insertions(+), 80 deletions(-)
create mode 100644 selftest/knownfail.d/smb2.durable-v2-open.bug15708
Changeset truncated at 500 lines:
diff --git a/selftest/knownfail b/selftest/knownfail
index 03f8b466994..31e70a1a9d3 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -218,7 +218,6 @@
^samba3.smb2.compound.interim2 # wrong return code (STATUS_CANCELLED)
^samba3.smb2.compound.aio.interim2 # wrong return code (STATUS_CANCELLED)
^samba3.smb2.lock.*replay_broken_windows # This tests the windows behaviour
-^samba3.smb2.lease.statopen3
^samba3.smb2.lease.unlink # we currently do not downgrade RH lease to R after unlink
^samba4.smb2.ioctl.compress_notsup.*\(ad_dc_ntvfs\)
^samba3.raw.session.*reauth2 # maybe fix this?
diff --git a/selftest/knownfail.d/smb2.durable-v2-open.bug15708 b/selftest/knownfail.d/smb2.durable-v2-open.bug15708
new file mode 100644
index 00000000000..3a6380c6d65
--- /dev/null
+++ b/selftest/knownfail.d/smb2.durable-v2-open.bug15708
@@ -0,0 +1,7 @@
+#
+# https://bugzilla.samba.org/show_bug.cgi?id=15708 is not fixed
+# yet, it requires some complex changes within handle_share_mode_lease()
+# merging logic of open_mode_check() and delay_for_oplock()...
+#
+^samba3.smb2.durable-v2-open.keep-disconnected-rh-with-rh-open
+^samba3.smb2.durable-v2-open.keep-disconnected-rh-with-rwh-open
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index 3fc7d56562a..4bbccdcd3bd 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -2703,16 +2703,25 @@ bool reset_share_mode_entry(
struct share_mode_data *d = NULL;
TDB_DATA key = locking_key(&id);
struct locking_tdb_data *ltdb = NULL;
- struct share_mode_entry e;
+ struct share_mode_entry e = { .pid.pid = 0 };
struct share_mode_entry_buf e_buf;
+ size_t old_idx;
+ size_t new_idx;
+ bool found;
NTSTATUS status;
- int cmp;
bool ret = false;
bool ok;
+ struct file_id_buf id_buf;
+ struct server_id_buf pid_buf1;
+ struct server_id_buf pid_buf2;
+ size_t low_idx1, low_idx2, low_num;
+ size_t mid_idx1, mid_idx2, mid_num;
+ size_t high_idx1, high_idx2, high_num;
+ TDB_DATA dbufs[4];
+ size_t num_dbufs = 0;
status = share_mode_lock_access_private_data(lck, &d);
if (!NT_STATUS_IS_OK(status)) {
- struct file_id_buf id_buf;
/* Any error recovery possible here ? */
DBG_ERR("share_mode_lock_access_private_data() failed for "
"%s - %s\n",
@@ -2728,29 +2737,54 @@ bool reset_share_mode_entry(
return false;
}
- if (ltdb->num_share_entries != 1) {
- DBG_DEBUG("num_share_modes=%zu\n", ltdb->num_share_entries);
- goto done;
- }
+ DBG_DEBUG("%s - num_share_modes=%zu\n",
+ file_id_str_buf(id, &id_buf),
+ ltdb->num_share_entries);
- ok = share_mode_entry_get(ltdb->share_entries, &e);
- if (!ok) {
- DBG_WARNING("share_mode_entry_get failed\n");
+ new_idx = share_mode_entry_find(
+ ltdb->share_entries,
+ ltdb->num_share_entries,
+ new_pid,
+ new_share_file_id,
+ &e,
+ &found);
+ if (found) {
+ DBG_ERR("%s - num_share_modes=%zu "
+ "found NEW[%s][%"PRIu64"]\n",
+ file_id_str_buf(id, &id_buf),
+ ltdb->num_share_entries,
+ server_id_str_buf(new_pid, &pid_buf2),
+ new_share_file_id);
goto done;
}
- cmp = share_mode_entry_cmp(
- old_pid, old_share_file_id, e.pid, e.share_file_id);
- if (cmp != 0) {
- struct server_id_buf tmp1, tmp2;
- DBG_WARNING("Expected pid=%s, file_id=%"PRIu64", "
- "got pid=%s, file_id=%"PRIu64"\n",
- server_id_str_buf(old_pid, &tmp1),
- old_share_file_id,
- server_id_str_buf(e.pid, &tmp2),
- e.share_file_id);
+ old_idx = share_mode_entry_find(
+ ltdb->share_entries,
+ ltdb->num_share_entries,
+ old_pid,
+ old_share_file_id,
+ &e,
+ &found);
+ if (!found) {
+ DBG_WARNING("%s - num_share_modes=%zu "
+ "OLD[%s][%"PRIu64"] not found\n",
+ file_id_str_buf(id, &id_buf),
+ ltdb->num_share_entries,
+ server_id_str_buf(old_pid, &pid_buf1),
+ old_share_file_id);
goto done;
}
+ DBG_DEBUG("%s - num_share_modes=%zu "
+ "OLD[%s][%"PRIu64"] => idx=%zu "
+ "NEW[%s][%"PRIu64"] => idx=%zu\n",
+ file_id_str_buf(id, &id_buf),
+ ltdb->num_share_entries,
+ server_id_str_buf(old_pid, &pid_buf1),
+ old_share_file_id,
+ old_idx,
+ server_id_str_buf(new_pid, &pid_buf2),
+ new_share_file_id,
+ new_idx);
e.pid = new_pid;
if (new_mid != UINT64_MAX) {
@@ -2764,11 +2798,248 @@ bool reset_share_mode_entry(
goto done;
}
- ltdb->share_entries = e_buf.buf;
+ /*
+ * The logic to remove the existing
+ * entry and add the new one at the
+ * same time is a bit complex because
+ * we need to keep the entries sorted.
+ *
+ * The following examples should catch
+ * the corner cases and show that
+ * the {low,mid,high}_{idx1,num} are
+ * correctly calculated and the new
+ * entry is put before or after the mid
+ * elements...
+ *
+ * 1.
+ * 0
+ * 1
+ * 2 <- old_idx
+ * new_idx -> 3
+ * 3
+ * 4
+ *
+ * low_idx1 = 0;
+ * low_idx2 = MIN(old_idx, new_idx); => 2
+ * low_num = low_idx2 - low_idx1; => 2
+ *
+ * if (new < old) => new; => no
+ *
+ * mid_idx1 = MIN(old_idx+1, new_idx); => 3
+ * mid_idx2 = MAX(old_idx, new_idx); => 3
+ * mid_num = mid_idx2 - mid_idx1; => 0
+ *
+ * if (new >= old) => new; => yes
+ *
+ * high_idx1 = MAX(old_idx+1, new_idx); => 3
+ * high_idx2 = num_share_entries; => 5
+ * high_num = high_idx2 - high_idx1 = 2
+ *
+ * 2.
+ * 0
+ * 1
+ * new_idx -> 2
+ * 2 <- old_idx
+ * 3
+ * 4
+ *
+ * low_idx1 = 0;
+ * low_idx2 = MIN(old_idx, new_idx); => 2
+ * low_num = low_idx2 - low_idx1; => 2
+ *
+ * if (new < old) => new; => no
+ *
+ * mid_idx1 = MIN(old_idx+1, new_idx); => 2
+ * mid_idx2 = MAX(old_idx, new_idx); => 2
+ * mid_num = mid_idx2 - mid_idx1; => 0
+ *
+ * if (new >= old) => new; => yes
+ *
+ * high_idx1 = MAX(old_idx+1, new_idx); => 3
+ * high_idx2 = num_share_entries; => 5
+ * high_num = high_idx2 - high_idx1 = 2
+ *
+ * 3.
+ * 0
+ * 1 <- old_idx
+ * 2
+ * new_idx -> 3
+ * 3
+ * 4
+ *
+ * low_idx1 = 0;
+ * low_idx2 = MIN(old_idx, new_idx); => 1
+ * low_num = low_idx2 - low_idx1; => 1
+ *
+ * if (new < old) => new; => no
+ *
+ * mid_idx1 = MIN(old_idx+1, new_idx); => 2
+ * mid_idx2 = MAX(old_idx, new_idx); => 3
+ * mid_num = mid_idx2 - mid_idx1; => 1
+ *
+ * if (new >= old) => new; => yes
+ *
+ * high_idx1 = MAX(old_idx+1, new_idx); => 3
+ * high_idx2 = num_share_entries; => 5
+ * high_num = high_idx2 - high_idx1 = 2
+ *
+ * 4.
+ * 0
+ * new_idx -> 1
+ * 1
+ * 2
+ * 3 <- old_idx
+ * 4
+ *
+ * low_idx1 = 0;
+ * low_idx2 = MIN(old_idx, new_idx); => 1
+ * low_num = low_idx2 - low_idx1; => 1
+ *
+ * if (new < old) => new; => yes
+ *
+ * mid_idx1 = MIN(old_idx+1, new_idx); => 1
+ * mid_idx2 = MAX(old_idx, new_idx); => 3
+ * mid_num = mid_idx2 - mid_idx1; => 2
+ *
+ * if (new >= old) => new; => no
+ *
+ * high_idx1 = MAX(old_idx+1, new_idx); => 4
+ * high_idx2 = num_share_entries; => 5
+ * high_num = high_idx2 - high_idx1 = 1
+ *
+ * 5.
+ * new_idx -> 0
+ * 0
+ * 1
+ * 2
+ * 3
+ * 4 <- old_idx
+ *
+ * low_idx1 = 0;
+ * low_idx2 = MIN(old_idx, new_idx); => 0
+ * low_num = low_idx2 - low_idx1; => 0
+ *
+ * if (new < old) => new; => yes
+ *
+ * mid_idx1 = MIN(old_idx+1, new_idx); => 0
+ * mid_idx2 = MAX(old_idx, new_idx); => 4
+ * mid_num = mid_idx2 - mid_idx1; => 4
+ *
+ * if (new >= old) => new; => no
+ *
+ * high_idx1 = MAX(old_idx+1, new_idx); => 5
+ * high_idx2 = num_share_entries; => 5
+ * high_num = high_idx2 - high_idx1 = 0
+ *
+ * 6.
+ * new_idx -> 0
+ * 0 <- old_idx
+ *
+ * low_idx1 = 0;
+ * low_idx2 = MIN(old_idx, new_idx); => 0
+ * low_num = low_idx2 - low_idx1; => 0
+ *
+ * if (new < old) => new; => no
+ *
+ * mid_idx1 = MIN(old_idx+1, new_idx); => 0
+ * mid_idx2 = MAX(old_idx, new_idx); => 0
+ * mid_num = mid_idx2 - mid_idx1; => 0
+ *
+ * if (new >= old) => new; => yes
+ *
+ * high_idx1 = MAX(old_idx+1, new_idx); => 1
+ * high_idx2 = num_share_entries; => 1
+ * high_num = high_idx2 - high_idx1 = 0
+ *
+ * 7.
+ * 0 <- old_idx
+ * new_idx -> 1
+ *
+ * low_idx1 = 0;
+ * low_idx2 = MIN(old_idx, new_idx); => 0
+ * low_num = low_idx2 - low_idx1; => 0
+ *
+ * if (new < old) => new; => no
+ *
+ * mid_idx1 = MIN(old_idx+1, new_idx); => 1
+ * mid_idx2 = MAX(old_idx, new_idx); => 1
+ * mid_num = mid_idx2 - mid_idx1; => 0
+ *
+ * if (new >= old) => new; => yes
+ *
+ * high_idx1 = MAX(old_idx+1, new_idx); => 1
+ * high_idx2 = num_share_entries; => 1
+ * high_num = high_idx2 - high_idx1 = 0
+ */
+ low_idx1 = 0;
+ low_idx2 = MIN(old_idx, new_idx);
+ low_num = low_idx2 - low_idx1;
+ mid_idx1 = MIN(old_idx+1, new_idx);
+ mid_idx2 = MAX(old_idx, new_idx);
+ mid_num = mid_idx2 - mid_idx1;
+ high_idx1 = MAX(old_idx+1, new_idx);
+ high_idx2 = ltdb->num_share_entries;
+ high_num = high_idx2 - high_idx1;
+
+ if (low_num != 0) {
+ dbufs[num_dbufs] = (TDB_DATA) {
+ .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
+ low_idx1 * SHARE_MODE_ENTRY_SIZE,
+ .dsize = low_num * SHARE_MODE_ENTRY_SIZE,
+ };
+ num_dbufs += 1;
+ }
+
+ if (new_idx < old_idx) {
+ dbufs[num_dbufs] = (TDB_DATA) {
+ .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
+ };
+ num_dbufs += 1;
+ }
+
+ if (mid_num != 0) {
+ dbufs[num_dbufs] = (TDB_DATA) {
+ .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
+ mid_idx1 * SHARE_MODE_ENTRY_SIZE,
+ .dsize = mid_num * SHARE_MODE_ENTRY_SIZE,
+ };
+ num_dbufs += 1;
+ }
+
+ if (new_idx >= old_idx) {
+ dbufs[num_dbufs] = (TDB_DATA) {
+ .dptr = e_buf.buf, .dsize = SHARE_MODE_ENTRY_SIZE,
+ };
+ num_dbufs += 1;
+ }
+
+ if (high_num != 0) {
+ dbufs[num_dbufs] = (TDB_DATA) {
+ .dptr = discard_const_p(uint8_t, ltdb->share_entries) +
+ high_idx1 * SHARE_MODE_ENTRY_SIZE,
+ .dsize = high_num * SHARE_MODE_ENTRY_SIZE,
+ };
+ num_dbufs += 1;
+ }
+ {
+ size_t i;
+ for (i=0; i<num_dbufs; i++) {
+ DBG_DEBUG("dbufs[%zu]=(%p, %zu)\n",
+ i,
+ dbufs[i].dptr,
+ dbufs[i].dsize);
+ }
+ }
+
+ /*
+ * We completely rewrite the entries...
+ */
+ ltdb->share_entries = NULL;
+ ltdb->num_share_entries = 0;
d->modified = true;
- status = share_mode_data_ltdb_store(d, key, ltdb, NULL, 0);
+ status = share_mode_data_ltdb_store(d, key, ltdb, dbufs, num_dbufs);
if (!NT_STATUS_IS_OK(status)) {
DBG_ERR("share_mode_data_ltdb_store failed: %s\n",
nt_errstr(status));
diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c
index dfb87dd3775..bd0c9f58e24 100644
--- a/source3/smbd/durable.c
+++ b/source3/smbd/durable.c
@@ -173,6 +173,12 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
return NT_STATUS_NOT_SUPPORTED;
}
+ if (fsp->current_lock_count != 0 &&
+ (fsp_lease_type(fsp) & SMB2_LEASE_WRITE) == 0)
+ {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
/*
* For now let it be simple and do not keep
* delete on close files durable open
@@ -500,19 +506,33 @@ static bool vfs_default_durable_reconnect_check_stat(
return true;
}
+struct durable_reconnect_state {
+ struct smbXsrv_open *op;
+ struct share_mode_entry *e;
+};
+
static bool durable_reconnect_fn(
struct share_mode_entry *e,
bool *modified,
void *private_data)
{
- struct share_mode_entry *dst_e = private_data;
+ struct durable_reconnect_state *state = private_data;
+ uint64_t id = state->op->global->open_persistent_id;
- if (dst_e->pid.pid != 0) {
+ if (e->share_file_id != id) {
+ return false; /* Look at potential other entries */
+ }
+
+ if (!server_id_is_disconnected(&e->pid)) {
+ return false; /* Look at potential other entries */
+ }
+
+ if (state->e->share_file_id == id) {
DBG_INFO("Found more than one entry, invalidating previous\n");
- dst_e->pid.pid = 0;
+ *state->e = (struct share_mode_entry) { .pid = { .pid = 0, }};
return true; /* end the loop through share mode entries */
}
- *dst_e = *e;
+ *state->e = *e;
return false; /* Look at potential other entries */
}
@@ -527,7 +547,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
const struct loadparm_substitution *lp_sub =
loadparm_s3_global_substitution();
struct share_mode_lock *lck;
- struct share_mode_entry e;
+ struct share_mode_entry e = { .pid = { .pid = 0, }};
+ struct durable_reconnect_state rstate = { .op = op, .e = &e, };
struct files_struct *fsp = NULL;
NTSTATUS status;
bool ok;
@@ -620,9 +641,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- e = (struct share_mode_entry) { .pid.pid = 0 };
-
- ok = share_mode_forall_entries(lck, durable_reconnect_fn, &e);
+ ok = share_mode_forall_entries(lck, durable_reconnect_fn, &rstate);
if (!ok) {
DBG_WARNING("share_mode_forall_entries failed\n");
status = NT_STATUS_INTERNAL_DB_ERROR;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 4f69a7749d8..736c6740b35 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2464,7 +2464,7 @@ struct delay_for_oplock_state {
bool first_open_attempt;
bool got_handle_lease;
bool got_oplock;
- bool have_other_lease;
+ bool disallow_write_lease;
uint32_t total_lease_types;
bool delay;
struct blocker_debug_state *blocker_debug_state;
@@ -2572,15 +2572,27 @@ static bool delay_for_oplock_fn(
}
if (!state->got_oplock &&
+ (e->op_type != NO_OPLOCK) &&
(e->op_type != LEASE_OPLOCK) &&
!share_entry_stale_pid(e)) {
state->got_oplock = true;
}
- if (!state->have_other_lease &&
+ /*
+ * Two things prevent a write lease
+ * to be granted:
+ *
+ * 1. Any oplock or lease (even broken to NONE)
+ * 2. An open with an access mask other than
+ * FILE_READ_ATTRIBUTES, FILE_WRITE_ATTRIBUTES
+ * or SYNCHRONIZE_ACCESS
+ */
+ if (!state->disallow_write_lease &&
+ (e->op_type != NO_OPLOCK || !is_oplock_stat_open(e->access_mask)) &&
!is_same_lease(fsp, e, lease) &&
- !share_entry_stale_pid(e)) {
- state->have_other_lease = true;
+ !share_entry_stale_pid(e))
+ {
+ state->disallow_write_lease = true;
}
--
Samba Shared Repository
More information about the samba-cvs
mailing list