The branch, master has been updated
via 9f45eae2928 smbd: only increment lease epoch if a lease was granted
via ca0363e5a7f smbtorture: add test "smb2.lease.lease-epoch"
via b0fb7db8ff3 smbtorture: correctly handle scale-out shares in
smb2.durable-v2-open.[persistent-]open-oplock
via ccae8981d60 smbtorture: correctly handle scale-out shares in
smb2.durable-v2-open.create-blob
via 5f8aaf9bcc0 smbtorture: fix smb2.durable-v2-open.open-lease and
smb2.durable-v2-open.persistent-open-lease
via b22b84a6948 smbstatus: avoid a crash with --json output if the
access_mask has SEC_STD_WRITE_OWNER
via fd1a011f790 smbd: avoid clobbering the file size, use info instead
via d31c8ff25cd smbd: move lp_locking() check inside file_has_brlocks()
via 21d10f0005a smbd: remove remnants from write cache handling which
was removed a long time ago
via 5133fe26a5e s3:smbd: remove an else branch in exit_server_common()
via 91b1511c3e5 smbd: fix handing of oplock_request and
INTERNAL_OPEN_ONLY
via 31759ee78b6 s3/rpc_server: fix "log file = %m"
via 492913dbb0a smbd-scavenger: call set_remote_machine_name()
via 4f02f6b714c smbd-cleanupd: call set_remote_machine_name() and
reopen_logs()
via 4301bb5b461 smbd-notifyd: call set_remote_machine_name()
via 95c7cd99c96 s3/locking: comment reformatting
from 3df388b8f14 smbd: use op->global->open_global_id for the
share_mode_entry.share_file_id
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 9f45eae2928bd2cb46fc827a348531acb471a549
Author: Ralph Boehme <[email protected]>
Date: Tue Sep 23 14:14:22 2025 +0200
smbd: only increment lease epoch if a lease was granted
From MS-SMB2 3.3.5.9.11 "Handling the SMB2_CREATE_REQUEST_LEASE_V2 Create
Context":
If the object store succeeds this request, Lease.LeaseState MUST be set
to the
new caching state. The server MUST increment Lease.Epoch by 1.
try_lease_upgrade() already has the same logic when checking for a possible
upgrade of an exisiting lease.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15933
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
Autobuild-User(master): Volker Lendecke <[email protected]>
Autobuild-Date(master): Fri Oct 10 17:02:26 UTC 2025 on atb-devel-224
commit ca0363e5a7f53cde4ae7223c36f21c2ae12318f9
Author: Ralph Boehme <[email protected]>
Date: Sat Sep 27 13:01:32 2025 +0200
smbtorture: add test "smb2.lease.lease-epoch"
Verifies the lease epoch is not incremented by the server (returns what the
client sent in the request) if a lease was not granted ie lease_level=NONE.
Test passes against Windows 2025.
From MS-SMB2 3.3.5.9.11 "Handling the SMB2_CREATE_REQUEST_LEASE_V2 Create
Context":
If the object store succeeds this request, Lease.LeaseState MUST be set
to the
new caching state. The server MUST increment Lease.Epoch by 1.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15933
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit b0fb7db8ff37ec58f93356edabc9a69d3ebc4790
Author: Ralph Boehme <[email protected]>
Date: Sat Aug 4 16:40:14 2018 +0200
smbtorture: correctly handle scale-out shares in
smb2.durable-v2-open.[persistent-]open-oplock
This ensures the tests work correctly against Windows on cluster shares
with and
without SMB2_SHARE_CAP_SCALEOUT.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit ccae8981d60ba34c0d1c03e052d8aca89f1a5bbd
Author: Ralph Boehme <[email protected]>
Date: Fri Feb 28 06:15:26 2025 +0100
smbtorture: correctly handle scale-out shares in
smb2.durable-v2-open.create-blob
On a share with SMB2_SHARE_CAP_SCALEOUT capability the cluster doesn't
grant batch oplocks, at most level-II oplocks and it also doesn't
grant durable-handles (v1 or v2) as they require an RWH-lease.
With this change the test passes against Windows Server 2025.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 5f8aaf9bcc0fa9891c72adf40e296e1cd2f7a826
Author: Ralph Boehme <[email protected]>
Date: Wed May 9 08:25:51 2018 +0200
smbtorture: fix smb2.durable-v2-open.open-lease and
smb2.durable-v2-open.persistent-open-lease
Only check the resulting lease state if we actually requested a lease and
correctly deal with SMB2_SHARE_CAP_SCALEOUT shares where the server grants
at
most R leases and no Durable Handles.
With this change the test passes against Windows Server 2025.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit b22b84a6948885e69a883e272634d9130c3a5592
Author: Ralph Boehme <[email protected]>
Date: Wed Jul 16 16:50:25 2025 +0200
smbstatus: avoid a crash with --json output if the access_mask has
SEC_STD_WRITE_OWNER
This was missing in access_mask[] triggering an assert when printing the
access
mask string:
...
#4 0x00007ffff79553cc in smb_panic (why=0x207b5c "assert failed: tomap ==
0") at ../../lib/util/fault.c:209
#5 0x000000000021ea2c in map_mask_to_json (root_json=0x7fffffffcd60,
tomap=524288, table=0x223440 <access_mask>) at
../../source3/utils/status_json.c:142
...
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit fd1a011f79034f6047aa3250532d017c5a61bf89
Author: Ralph Boehme <[email protected]>
Date: Wed Sep 24 19:30:08 2025 +0200
smbd: avoid clobbering the file size, use info instead
This is a better implementation of 215b2c741a93023d13e8a9f82739ac3e91b64a66
and
also prepares for future changes where I'll need the current size.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit d31c8ff25cd55106ac43aa3a041b96a956e53f9e
Author: Ralph Boehme <[email protected]>
Date: Mon Sep 22 17:28:23 2025 +0200
smbd: move lp_locking() check inside file_has_brlocks()
Avoids doing the check at every caller.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 21d10f0005a728c265da445e82b80c8955cbf060
Author: Ralph Boehme <[email protected]>
Date: Wed Oct 1 11:45:43 2025 +0200
smbd: remove remnants from write cache handling which was removed a long
time ago
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 5133fe26a5ed8ee823da8e09f98f4986e800595e
Author: Ralph Boehme <[email protected]>
Date: Sun Feb 25 09:48:53 2018 +0100
s3:smbd: remove an else branch in exit_server_common()
No change in behaviour.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 91b1511c3e537ec8757228c81ea1c9c9772c8d94
Author: Ralph Boehme <[email protected]>
Date: Sun Aug 24 08:45:39 2025 +0200
smbd: fix handing of oplock_request and INTERNAL_OPEN_ONLY
Avoid overwriting INTERNAL_OPEN_ONLY in oplock_request and fix setting
oplock_request to INTERNAL_OPEN_ONLY.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 31759ee78b61aa578454e7c3e494c5ea89cc1e36
Author: Ralph Boehme <[email protected]>
Date: Sat Sep 27 12:02:35 2025 +0200
s3/rpc_server: fix "log file = %m"
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 492913dbb0a8b6ed7911dd9ce0c22787feee02ba
Author: Ralph Boehme <[email protected]>
Date: Sat Sep 27 11:32:29 2025 +0200
smbd-scavenger: call set_remote_machine_name()
Makes "log file = %m" work.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 4f02f6b714cb34d42e30f6819ac63c1bfafa1361
Author: Ralph Boehme <[email protected]>
Date: Sat Sep 27 11:32:02 2025 +0200
smbd-cleanupd: call set_remote_machine_name() and reopen_logs()
Makes "log file = %m" work.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 4301bb5b461c5800887f1c9e3bf549ebec81818b
Author: Ralph Boehme <[email protected]>
Date: Sat Sep 27 11:31:04 2025 +0200
smbd-notifyd: call set_remote_machine_name()
Makes "log file = %m" work.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
commit 95c7cd99c96687f512077cba6f99ed70dd30c566
Author: Ralph Boehme <[email protected]>
Date: Thu Jul 17 11:23:34 2025 +0200
s3/locking: comment reformatting
Prepares for upcoming changes.
Signed-off-by: Ralph Boehme <[email protected]>
Reviewed-by: Volker Lendecke <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
source3/include/locking.h | 13 +++--
source3/locking/brlock.c | 4 ++
source3/rpc_server/rpc_host.c | 3 ++
source3/rpc_server/rpc_worker.c | 3 ++
source3/smbd/close.c | 7 +--
source3/smbd/open.c | 36 +++++++------
source3/smbd/scavenger.c | 2 +
source3/smbd/server.c | 4 ++
source3/smbd/server_exit.c | 11 ++--
source3/utils/status_json.c | 1 +
source4/torture/smb2/durable_v2_open.c | 96 +++++++++++++++++++++++++++++----
source4/torture/smb2/lease.c | 99 ++++++++++++++++++++++++++++++++++
12 files changed, 236 insertions(+), 43 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/include/locking.h b/source3/include/locking.h
index f9eb502b758..1c4c6d7ccad 100644
--- a/source3/include/locking.h
+++ b/source3/include/locking.h
@@ -49,10 +49,15 @@ struct files_struct;
struct byte_range_lock;
typedef uint64_t br_off;
-/* Internal structure in brlock.tdb.
- The data in brlock records is an unsorted linear array of these
- records. It is unnecessary to store the count as tdb provides the
- size of the record */
+/*
+ * Internal structure in brlock.tdb
+ *
+ * The data in brlock records is an unsorted linear array of these
+ * records.
+ *
+ * It is unnecessary to store the count as tdb provides the size of
+ * the record.
+ */
struct lock_struct {
struct lock_context context;
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index e0f5c14c302..39480a3275b 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -2004,6 +2004,10 @@ bool file_has_brlocks(files_struct *fsp)
struct byte_range_lock *br_lck = NULL;
uint i, num_locks;
+ if (!lp_locking(fsp->conn->params)) {
+ return false;
+ }
+
br_lck = brl_get_locks_readonly(fsp);
if (br_lck == NULL) {
return false;
diff --git a/source3/rpc_server/rpc_host.c b/source3/rpc_server/rpc_host.c
index b88cdf48cc3..73099ea5926 100644
--- a/source3/rpc_server/rpc_host.c
+++ b/source3/rpc_server/rpc_host.c
@@ -71,6 +71,7 @@
#include "nsswitch/winbind_client.h"
#include "libcli/security/dom_sid.h"
#include "libcli/security/security_token.h"
+#include "source3/lib/substitute.h"
extern bool override_logfile;
@@ -2884,6 +2885,8 @@ int main(int argc, const char *argv[])
dump_core_setup(progname, lp_logfile(frame, lp_sub));
+ set_remote_machine_name("samba-dcerpcd", false);
+
reopen_logs();
DBG_STARTUP_NOTICE("%s version %s started.\n%s\n",
diff --git a/source3/rpc_server/rpc_worker.c b/source3/rpc_server/rpc_worker.c
index 9533c559863..e9dc56ef983 100644
--- a/source3/rpc_server/rpc_worker.c
+++ b/source3/rpc_server/rpc_worker.c
@@ -45,6 +45,7 @@
#include "libcli/security/security_token.h"
#include "libcli/security/dom_sid.h"
#include "source3/include/proto.h"
+#include "source3/lib/substitute.h"
/*
* This is the generic code that becomes the
@@ -1143,6 +1144,8 @@ int rpc_worker_main(
/* Ignore children - no zombies. */
CatchChild();
+ set_remote_machine_name(progname, false);
+
reopen_logs();
DBG_STARTUP_NOTICE("%s version %s started.\n%s\n",
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index ce04056fc34..d2d53e779e1 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -849,12 +849,7 @@ static NTSTATUS close_normal_file(struct smb_request *req,
files_struct *fsp,
NT_STATUS_RANGE_NOT_LOCKED);
}
- /*
- * If we're flushing on a close we can get a write
- * error here, we must remember this.
- */
-
- if (NT_STATUS_IS_OK(status) && fsp->op != NULL) {
+ if (fsp->op != NULL) {
is_durable = fsp->op->global->durable;
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index e898829c52c..a26cf653612 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2045,7 +2045,10 @@ static NTSTATUS grant_new_fsp_lease(struct files_struct
*fsp,
fsp->lease->lease.parent_lease_key = lease->parent_lease_key;
fsp->lease->lease.lease_flags = lease->lease_flags;
fsp->lease->lease.lease_state = granted;
- fsp->lease->lease.lease_epoch = lease->lease_epoch + 1;
+ fsp->lease->lease.lease_epoch = lease->lease_epoch;
+ if (granted != 0) {
+ fsp->lease->lease.lease_epoch++;
+ }
status = leases_db_add(client_guid,
&lease->lease_key,
@@ -2130,6 +2133,7 @@ struct delay_for_oplock_state {
bool will_overwrite;
uint32_t delay_mask;
bool first_open_attempt;
+ int info;
bool got_handle_lease;
bool got_oplock;
bool disallow_write_lease;
@@ -2373,6 +2377,7 @@ static NTSTATUS delay_for_oplock(files_struct *fsp,
bool have_sharing_violation,
uint32_t create_disposition,
bool first_open_attempt,
+ int info,
int *poplock_type,
uint32_t *pgranted,
struct blocker_debug_state
**blocker_debug_state)
@@ -2381,6 +2386,7 @@ static NTSTATUS delay_for_oplock(files_struct *fsp,
.fsp = fsp,
.lease = lease,
.first_open_attempt = first_open_attempt,
+ .info = info,
};
uint32_t requested;
uint32_t granted;
@@ -2486,7 +2492,7 @@ grant:
}
}
- if (lp_locking(fsp->conn->params) && file_has_brlocks(fsp)) {
+ if (info != FILE_WAS_OVERWRITTEN && file_has_brlocks(fsp)) {
DBG_DEBUG("file %s has byte range locks\n",
fsp_str_dbg(fsp));
granted &= ~(SMB2_LEASE_READ | SMB2_LEASE_HANDLE);
@@ -2571,6 +2577,7 @@ static NTSTATUS handle_share_mode_lease(
int oplock_request,
const struct smb2_lease *lease,
bool first_open_attempt,
+ int info,
int *poplock_type,
uint32_t *pgranted,
struct blocker_debug_state **blocker_debug_state)
@@ -2623,6 +2630,7 @@ static NTSTATUS handle_share_mode_lease(
sharing_violation,
create_disposition,
first_open_attempt,
+ info,
poplock_type,
pgranted,
blocker_debug_state);
@@ -3071,7 +3079,8 @@ static NTSTATUS check_and_store_share_mode(
uint32_t share_access,
int oplock_request,
const struct smb2_lease *lease,
- bool first_open_attempt)
+ bool first_open_attempt,
+ int info)
{
NTSTATUS status;
int oplock_type = NO_OPLOCK;
@@ -3099,6 +3108,7 @@ static NTSTATUS check_and_store_share_mode(
oplock_request,
lease,
first_open_attempt,
+ info,
&oplock_type,
&granted_lease,
&blocker_debug_state);
@@ -3429,6 +3439,7 @@ struct open_ntcreate_lock_state {
int oplock_request;
const struct smb2_lease *lease;
bool first_open_attempt;
+ int info;
bool keep_locked;
NTSTATUS status;
share_mode_entry_prepare_unlock_fn_t cleanup_fn;
@@ -3456,7 +3467,8 @@ static void open_ntcreate_lock_add_entry(struct
share_mode_lock *lck,
state->share_access,
state->oplock_request,
state->lease,
- state->first_open_attempt);
+ state->first_open_attempt,
+ state->info);
if (!NT_STATUS_IS_OK(state->status)) {
return;
}
@@ -3816,7 +3828,7 @@ static NTSTATUS open_file_ntcreate(connection_struct
*conn,
* which adds FILE_WRITE_DATA to open_access_mask.
*/
if (is_oplock_stat_open(open_access_mask) && lease == NULL) {
- oplock_request = NO_OPLOCK;
+ oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK;
}
}
@@ -4063,15 +4075,6 @@ static NTSTATUS open_file_ntcreate(connection_struct
*conn,
} else {
if (flags & O_TRUNC) {
info = FILE_WAS_OVERWRITTEN;
- /*
- * We did not truncate the file yet, we're doing that
- * explicitly with SMB_VFS_FTRUNCATE() below under the
- * sharemode glock. For correct handling of RH leases in
- * the presence of byterange locks, the leases code
- * needs the "correct" filesize which should be 0 at
- * this place if we did the O_TRUNC at open() time.
- */
- fsp->fsp_name->st.st_ex_size = 0;
} else {
info = FILE_WAS_OPENED;
}
@@ -4100,6 +4103,7 @@ static NTSTATUS open_file_ntcreate(connection_struct
*conn,
.oplock_request = oplock_request,
.lease = lease,
.first_open_attempt = first_open_attempt,
+ .info = info,
.keep_locked = keep_locked,
};
@@ -5163,7 +5167,7 @@ static NTSTATUS open_directory(connection_struct *conn,
/*
* No oplocks on directories, only leases
*/
- oplock_request = NO_OPLOCK;
+ oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK;
}
lck_state = (struct open_ntcreate_lock_state) {
@@ -6169,7 +6173,7 @@ static NTSTATUS create_file_unixpath(connection_struct
*conn,
}
if (req == NULL) {
- oplock_request |= INTERNAL_OPEN_ONLY;
+ oplock_request = INTERNAL_OPEN_ONLY;
}
if (lease != NULL) {
diff --git a/source3/smbd/scavenger.c b/source3/smbd/scavenger.c
index 2e04df662ef..194ff2bdaaf 100644
--- a/source3/smbd/scavenger.c
+++ b/source3/smbd/scavenger.c
@@ -31,6 +31,7 @@
#include "lib/util/server_id.h"
#include "lib/util/util_process.h"
#include "lib/util/sys_rw_data.h"
+#include "source3/lib/substitute.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_SCAVENGER
@@ -255,6 +256,7 @@ static bool smbd_scavenger_start(struct
smbd_scavenger_state *state)
}
process_set_title("smbd-scavenger", "scavenger");
+ set_remote_machine_name("scavenger", false);
reopen_logs();
state->am_scavenger = true;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 4e51fb6396d..0d5c4347353 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -496,6 +496,7 @@ static bool smbd_notifyd_init(struct messaging_context
*msg, bool interactive,
}
process_set_title("smbd-notifyd", "notifyd");
+ set_remote_machine_name("notifyd", false);
reopen_logs();
@@ -715,6 +716,9 @@ static bool cleanupd_init(struct messaging_context *msg,
bool interactive,
}
process_set_title("smbd-cleanupd", "cleanupd");
+ set_remote_machine_name("cleanupd", false);
+
+ reopen_logs();
se = tevent_add_signal(ev,
ev,
diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c
index ed399199b87..1ae32dc5c53 100644
--- a/source3/smbd/server_exit.c
+++ b/source3/smbd/server_exit.c
@@ -226,12 +226,11 @@ static void exit_server_common(enum server_exit_reason
how,
/* Notreached. */
exit(1);
- } else {
- DEBUG(3,("Server exit (%s)\n",
- (reason ? reason : "normal exit")));
- if (am_parent) {
- pidfile_unlink(lp_pid_directory(), "smbd");
- }
+ }
+
+ DBG_NOTICE("Server exit (%s)\n", reason ? reason : "normal exit");
+ if (am_parent) {
+ pidfile_unlink(lp_pid_directory(), "smbd");
}
exit(0);
diff --git a/source3/utils/status_json.c b/source3/utils/status_json.c
index ad25ed5d91b..fba0f40508f 100644
--- a/source3/utils/status_json.c
+++ b/source3/utils/status_json.c
@@ -157,6 +157,7 @@ static const struct mask2txt access_mask[] = {
{SEC_STD_DELETE, "DELETE"},
{SEC_STD_READ_CONTROL, "READ_CONTROL"},
{SEC_STD_WRITE_DAC, "WRITE_DAC"},
+ {SEC_STD_WRITE_OWNER, "WRITE_OWNER"},
{SEC_STD_SYNCHRONIZE, "SYNCHRONIZE"},
{SEC_FLAG_SYSTEM_SECURITY, "ACCESS_SYSTEM_SECURITY"},
{0, NULL}
diff --git a/source4/torture/smb2/durable_v2_open.c
b/source4/torture/smb2/durable_v2_open.c
index 3df9ec4db7f..698778ba287 100644
--- a/source4/torture/smb2/durable_v2_open.c
+++ b/source4/torture/smb2/durable_v2_open.c
@@ -112,6 +112,24 @@ bool test_durable_v2_open_create_blob(struct
torture_context *tctx,
struct GUID create_guid = GUID_random();
bool ret = true;
struct smbcli_options options;
+ uint32_t share_capabilities;
+ bool share_is_so;
+ uint8_t expected_oplock_granted;
+ bool expected_dhv2_granted;
+ uint32_t expected_dhv2_timeout;
+
+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
+
+ if (share_is_so) {
+ expected_oplock_granted = SMB2_OPLOCK_LEVEL_II;
+ expected_dhv2_granted = false;
+ expected_dhv2_timeout = 0;
+ } else {
+ expected_oplock_granted = SMB2_OPLOCK_LEVEL_BATCH;
+ expected_dhv2_granted = true;
+ expected_dhv2_timeout = 300*1000;
+}
options = tree->session->transport->options;
@@ -135,11 +153,11 @@ bool test_durable_v2_open_create_blob(struct
torture_context *tctx,
_h = io.out.file.handle;
h = &_h;
CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
- CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
+ CHECK_VAL(io.out.oplock_level, expected_oplock_granted);
CHECK_VAL(io.out.durable_open, false);
- CHECK_VAL(io.out.durable_open_v2, true);
+ CHECK_VAL(io.out.durable_open_v2, expected_dhv2_granted);
CHECK_VAL(io.out.persistent_open, false);
- CHECK_VAL(io.out.timeout, 300*1000);
+ CHECK_VAL(io.out.timeout, expected_dhv2_timeout);
/* disconnect */
TALLOC_FREE(tree);
@@ -269,13 +287,44 @@ static bool test_one_durable_v2_open_oplock(struct
torture_context *tctx,
{
NTSTATUS status;
TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ uint32_t share_capabilities;
+ bool share_is_so;
struct smb2_handle _h;
struct smb2_handle *h = NULL;
bool ret = true;
struct smb2_create io;
+ uint8_t expected_oplock_level;
+ bool expected_durable;
smb2_util_unlink(tree, fname);
+ share_capabilities = smb2cli_tcon_capabilities(tree->smbXcli);
+ share_is_so = share_capabilities & SMB2_SHARE_CAP_SCALEOUT;
+
+ expected_oplock_level = smb2_util_oplock_level(test.level);
+ expected_durable = test.durable;
+
+ if (share_is_so) {
+ /*
+ * MS-SMB2 3.3.5.9 Receiving an SMB2 CREATE Request
+ *
+ * If Connection.Dialect belongs to the SMB 3.x dialect family,
+ * TreeConnect.Share.Type is STYPE_CLUSTER_SOFS as specified in
+ * [MS-SRVS] section 2.2.2.4, and the RequestedOplockLevel is
+ * SMB2_OPLOCK_LEVEL_BATCH, the server MUST set
+ * RequestedOplockLevel to SMB2_OPLOCK_LEVEL_II.
+ */
+ if (expected_oplock_level == SMB2_OPLOCK_LEVEL_BATCH) {
+ expected_oplock_level = SMB2_OPLOCK_LEVEL_II;
+ }
+ /*
+ * No Durable Handles on SOFS shares, only Persistent Handles.
+ */
+ if (!request_persistent) {
+ expected_durable = false;
+ }
+ }
+
smb2_oplock_create_share(&io, fname,
smb2_util_share_access(test.share_mode),
smb2_util_oplock_level(test.level));
@@ -290,9 +339,9 @@ static bool test_one_durable_v2_open_oplock(struct
torture_context *tctx,
h = &_h;
CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
CHECK_VAL(io.out.durable_open, false);
- CHECK_VAL(io.out.durable_open_v2, test.durable);
+ CHECK_VAL(io.out.durable_open_v2, expected_durable);
CHECK_VAL(io.out.persistent_open, test.persistent);
- CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level(test.level));
+ CHECK_VAL(io.out.oplock_level, expected_oplock_level);
done:
if (h != NULL) {
@@ -422,6 +471,7 @@ static bool test_one_durable_v2_open_lease(struct
torture_context *tctx,
struct smb2_tree *tree,
const char *fname,
bool request_persistent,
+ bool share_is_so,
struct durable_open_vs_lease test)
{
NTSTATUS status;
@@ -432,11 +482,22 @@ static bool test_one_durable_v2_open_lease(struct
torture_context *tctx,
struct smb2_create io;
struct smb2_lease ls;
uint64_t lease;
+ uint8_t expected_lease_granted;
+ bool expected_durable;
smb2_util_unlink(tree, fname);
lease = random();
+ expected_lease_granted = smb2_util_lease_state(test.type);
+ expected_durable = test.durable;
+ if (share_is_so) {
+ expected_lease_granted &= SMB2_LEASE_READ;
+ if (!request_persistent) {
+ expected_durable = false;
+ }
+ }
+
smb2_lease_create_share(&io, &ls, false /* dir */, fname,
smb2_util_share_access(test.share_mode),
lease,
@@ -452,13 +513,15 @@ static bool test_one_durable_v2_open_lease(struct
torture_context *tctx,
h = &_h;
CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
CHECK_VAL(io.out.durable_open, false);
- CHECK_VAL(io.out.durable_open_v2, test.durable);
+ CHECK_VAL(io.out.durable_open_v2, expected_durable);
CHECK_VAL(io.out.persistent_open, test.persistent);
- CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
- CHECK_VAL(io.out.lease_response.lease_key.data[0], lease);
- CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease);
- CHECK_VAL(io.out.lease_response.lease_state,
- smb2_util_lease_state(test.type));
+ if (smb2_util_lease_state(test.type) != 0) {
+ CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE);
+ CHECK_VAL(io.out.lease_response.lease_key.data[0], lease);
+ CHECK_VAL(io.out.lease_response.lease_key.data[1], ~lease);
+ CHECK_VAL(io.out.lease_response.lease_state,
+ expected_lease_granted);
+ }
done:
if (h != NULL) {
smb2_util_close(tree, *h);
@@ -473,6 +536,7 @@ static bool test_durable_v2_open_lease_table(struct
torture_context *tctx,
struct smb2_tree *tree,
const char *fname,
bool request_persistent,
+ bool share_is_so,
struct durable_open_vs_lease
*table,
uint8_t num_tests)
{
@@ -486,6 +550,7 @@ static bool test_durable_v2_open_lease_table(struct
torture_context *tctx,
tree,
fname,
request_persistent,
+ share_is_so,
table[i]);
if (ret == false) {
goto done;
@@ -504,17 +569,23 @@ bool test_durable_v2_open_lease(struct torture_context
*tctx,
char fname[256];
bool ret = true;
--
Samba Shared Repository