oplock patchset

Volker Lendecke Volker.Lendecke at SerNet.DE
Thu Sep 5 18:22:46 CEST 2013


Hi!

Attached find a patchset that fixes oplock break without
strict allocate. Also remove the FORCE_OPLOCK_BREAK_TO_NONE
flag. This is not needed anymore, it seems that all Windows
since SMB2 was introduced does the 2-step oplock break to
none for the set_file_length and set_allocation_info
name-based calls.

Please review&push!

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de

*****************************************************************
visit us on it-sa:IT security exhibitions in Nürnberg, Germany
October 8th - 10th 2013, hall 12, booth 333
free tickets available via code 270691 on: www.it-sa.de/gutschein
******************************************************************
-------------- next part --------------
From e0635efaf0b69ecdc9ef73bab72d77ab25e1057b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 5 Sep 2013 10:33:21 +0000
Subject: [PATCH 1/4] smbd: Fix breaking level2 on allocate

This needs doing even if we don't have strct allocate set. The client
should not know that we lied. Fixes smb2.oplock.batch12.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 selftest/knownfail |    1 -
 source3/smbd/vfs.c |   13 +++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/selftest/knownfail b/selftest/knownfail
index 6fe7ce5..8b89f00 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -203,7 +203,6 @@
 ^samba3.smb2.lease.oplock
 ^samba3.smb2.lease.multibreak
 ^samba3.smb2.lease.v2_request
-^samba3.smb2.oplock.batch12
 ^samba3.smb2.oplock.batch20
 ^samba3.smb2.oplock.stream1
 ^samba3.smb2.streams.rename
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 49609d0..ca6500c 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -561,16 +561,17 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
 		return ret;
 	}
 
-	if (!lp_strict_allocate(SNUM(fsp->conn)))
-		return 0;
-
 	/* Grow - we need to test if we have enough space. */
 
 	contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
 
-	/* See if we have a syscall that will allocate beyond end-of-file
-	   without changing EOF. */
-	ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_KEEP_SIZE, 0, len);
+	if (lp_strict_allocate(SNUM(fsp->conn))) {
+		/* See if we have a syscall that will allocate beyond
+		   end-of-file without changing EOF. */
+		ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_KEEP_SIZE, 0, len);
+	} else {
+		ret = 0;
+	}
 
 	contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
 
-- 
1.7.9.5


From 49475b3debd297157129ad9e4c5f4c26f20439f5 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 5 Sep 2013 12:03:07 +0000
Subject: [PATCH 2/4] torture: Add a new w2k12 target

W2k12 seems to do the 2-step break to none, try running raw.oplock.batch12
against it.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source4/torture/smbtorture.c |    2 ++
 source4/torture/util.h       |    1 +
 2 files changed, 3 insertions(+)

diff --git a/source4/torture/smbtorture.c b/source4/torture/smbtorture.c
index 1a1fa34..cb0be97 100644
--- a/source4/torture/smbtorture.c
+++ b/source4/torture/smbtorture.c
@@ -498,6 +498,8 @@ int main(int argc,char *argv[])
 		lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
 		lpcfg_set_cmdline(cmdline_lp_ctx,
 		    "torture:invalid_lock_range_support", "false");
+	} else if (strcmp(target, "w2k12") == 0) {
+		lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k12", "true");
 	} else if (strcmp(target, "win7") == 0) {
 		lpcfg_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
 		lpcfg_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
diff --git a/source4/torture/util.h b/source4/torture/util.h
index 3c72309..4695710 100644
--- a/source4/torture/util.h
+++ b/source4/torture/util.h
@@ -31,6 +31,7 @@ struct smbcli_tree;
 #define TARGET_IS_WINXP(_tctx) (torture_setting_bool(_tctx, "winxp", false))
 #define TARGET_IS_W2K3(_tctx) (torture_setting_bool(_tctx, "w2k3", false))
 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
+#define TARGET_IS_W2K12(_tctx) (torture_setting_bool(_tctx, "w2k12", false))
 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
-- 
1.7.9.5


From c0df9ef1295b2793dbf13cef22e2e888c28113b7 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 5 Sep 2013 13:03:56 +0000
Subject: [PATCH 3/4] torture: Adapt raw.oplock to w2k12

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source4/torture/raw/oplock.c |   24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c
index de3d917..ad21623 100644
--- a/source4/torture/raw/oplock.c
+++ b/source4/torture/raw/oplock.c
@@ -259,6 +259,14 @@ static uint8_t get_break_level1_to_none_count(struct torture_context *tctx)
 	    2 : 1;
 }
 
+static uint8_t get_setinfo_break_count(struct torture_context *tctx)
+{
+	if (TARGET_IS_W2K12(tctx)) {
+		return 2;
+	}
+	return 1;
+}
+
 static bool test_raw_oplock_exclusive1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
 {
 	const char *fname = BASEDIR "\\test_exclusive1.dat";
@@ -477,7 +485,7 @@ static bool test_raw_oplock_exclusive3(struct torture_context *tctx, struct smbc
 
 	CHECK_STATUS(tctx, status, NT_STATUS_OK);
 	torture_wait_for_oplock_break(tctx);
-	CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
+	CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
 	CHECK_VAL(break_info.failures, 0);
 	CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
 
@@ -767,7 +775,7 @@ static bool test_raw_oplock_exclusive7(struct torture_context *tctx,
 	torture_wait_for_oplock_break(tctx);
 	CHECK_VAL(break_info.failures, 0);
 
-	if (TARGET_IS_WINXP(tctx)) {
+	if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
 		/* XP incorrectly breaks to level2. */
 		CHECK_VAL(break_info.count, 1);
 		CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -800,6 +808,10 @@ static bool test_raw_oplock_exclusive7(struct torture_context *tctx,
 		/* XP already broke to level2. */
 		CHECK_VAL(break_info.failures, 0);
 		CHECK_VAL(break_info.count, 0);
+	} else if (TARGET_IS_W2K12(tctx)) {
+		/* no break */
+		CHECK_VAL(break_info.count, 0);
+		CHECK_VAL(break_info.level, 0);
 	} else {
 		/* Break to level 2 expected. */
 		CHECK_VAL(break_info.count, 1);
@@ -1792,7 +1804,7 @@ static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_
 	CHECK_STATUS(tctx, status, NT_STATUS_OK);
 
 	torture_wait_for_oplock_break(tctx);
-	CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
+	CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
 	CHECK_VAL(break_info.failures, 0);
 	CHECK_VAL(break_info.level, 0);
 
@@ -1869,7 +1881,7 @@ static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_
 	CHECK_STATUS(tctx, status, NT_STATUS_OK);
 
 	torture_wait_for_oplock_break(tctx);
-	CHECK_VAL(break_info.count, get_break_level1_to_none_count(tctx));
+	CHECK_VAL(break_info.count, get_setinfo_break_count(tctx));
 	CHECK_VAL(break_info.failures, 0);
 	CHECK_VAL(break_info.level, 0);
 
@@ -2397,7 +2409,7 @@ static bool test_raw_oplock_batch19(struct torture_context *tctx, struct smbcli_
 
 	CHECK_VAL(break_info.failures, 0);
 
-	if (TARGET_IS_WINXP(tctx)) {
+	if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
 		/* Win XP breaks to level2. */
 		CHECK_VAL(break_info.count, 1);
 		CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
@@ -2759,7 +2771,7 @@ static bool test_raw_oplock_batch20(struct torture_context *tctx, struct smbcli_
 	torture_wait_for_oplock_break(tctx);
 	CHECK_VAL(break_info.failures, 0);
 
-	if (TARGET_IS_WINXP(tctx)) {
+	if (TARGET_IS_WINXP(tctx) || TARGET_IS_W2K12(tctx)) {
 		/* Win XP breaks to level2. */
 		CHECK_VAL(break_info.count, 1);
 		CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
-- 
1.7.9.5


From ab78161442774ab2f824766c13a8dc35fecf0961 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 4 Sep 2013 17:26:30 +0200
Subject: [PATCH 4/4] smbd: Remove FORCE_OPLOCK_BREAK_TO_NONE

This flag existed to break an exclusive or batch oplock in just one
instead of two steps down to "no oplock" when we did an allocation or file
size change.  Running raw.oplock against W2k12 differs in this respect
from W2k3: W2k12 takes two steps (via level2) to break to none. This
removes the special flag that we only had for compatibility with systems
older than W2k12...

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/include/smb.h        |    4 ++--
 source3/smbd/open.c          |   15 ++-------------
 source3/smbd/oplock.c        |    1 -
 source3/smbd/trans2.c        |    5 ++---
 source4/torture/raw/oplock.c |    3 +++
 5 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/source3/include/smb.h b/source3/include/smb.h
index 9dd8c58..8dd6555 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -675,10 +675,10 @@ enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT,
 				 * write. */
 /* #define DEFERRED_OPEN_ENTRY 		0x20 */   /* Not used anymore */
 /* #define UNUSED_SHARE_MODE_ENTRY 	0x40 */   /* Not used anymore */
-#define FORCE_OPLOCK_BREAK_TO_NONE 	0x80
+/* #define FORCE_OPLOCK_BREAK_TO_NONE 	0x80 */   /* Not used anymore */
 
 /* None of the following should ever appear in fsp->oplock_request. */
-#define SAMBA_PRIVATE_OPLOCK_MASK (INTERNAL_OPEN_ONLY|FORCE_OPLOCK_BREAK_TO_NONE)
+#define SAMBA_PRIVATE_OPLOCK_MASK (INTERNAL_OPEN_ONLY)
 
 #define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)EXCLUSIVE_OPLOCK|(unsigned int)BATCH_OPLOCK))
 #define BATCH_OPLOCK_TYPE(lck) ((lck) & (unsigned int)BATCH_OPLOCK)
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index c28d2a3..f4210d7 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1184,14 +1184,6 @@ static NTSTATUS send_break_message(files_struct *fsp,
 	/* Create the message. */
 	share_mode_entry_to_message(msg, exclusive);
 
-	/* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We
-	   don't want this set in the share mode struct pointed to by lck. */
-
-	if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) {
-		SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET,
-			exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
-	}
-
 	status = messaging_send_buf(fsp->conn->sconn->msg_ctx, exclusive->pid,
 				    MSG_SMB_BREAK_REQUEST,
 				    (uint8 *)msg,
@@ -1914,10 +1906,7 @@ static int calculate_open_access_flags(uint32_t access_mask,
 	 * mean the same thing under DOS and Unix.
 	 */
 
-	need_write =
-		((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ||
-		 (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE));
-
+	need_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA));
 	if (!need_write) {
 		return O_RDONLY;
 	}
@@ -2181,7 +2170,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 
 	open_access_mask = access_mask;
 
-	if ((flags2 & O_TRUNC) || (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) {
+	if (flags2 & O_TRUNC) {
 		open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
 	}
 
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 434bafa..4cdf68b 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -535,7 +535,6 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
 	use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) && koplocks;
 
 	if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) &&
-	    !(msg.op_type & FORCE_OPLOCK_BREAK_TO_NONE) &&
 	    !(use_kernel && !(koplocks->flags & KOPLOCKS_LEVEL2_SUPPORTED)) &&
 	    lp_level2_oplocks(SNUM(fsp->conn))) {
 		break_to_level2 = True;
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index aaf0e62..e6bb12c 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5900,7 +5900,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
 		FILE_OPEN,				/* create_disposition*/
 		0,					/* create_options */
 		FILE_ATTRIBUTE_NORMAL,			/* file_attributes */
-		FORCE_OPLOCK_BREAK_TO_NONE,		/* oplock_request */
+		0,					/* oplock_request */
 		0,					/* allocation_size */
 		0,					/* private_flags */
 		NULL,					/* sd */
@@ -6891,7 +6891,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
 		FILE_OPEN,				/* create_disposition*/
 		0,					/* create_options */
 		FILE_ATTRIBUTE_NORMAL,			/* file_attributes */
-		FORCE_OPLOCK_BREAK_TO_NONE,		/* oplock_request */
+		0,					/* oplock_request */
 		0,					/* allocation_size */
 		0,					/* private_flags */
 		NULL,					/* sd */
@@ -6919,7 +6919,6 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
 	 * if there are no pending writes.
 	 */
 	trigger_write_time_update_immediate(new_fsp);
-
 	close_file(req, new_fsp, NORMAL_CLOSE);
 	return NT_STATUS_OK;
 }
diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c
index ad21623..c2e086a 100644
--- a/source4/torture/raw/oplock.c
+++ b/source4/torture/raw/oplock.c
@@ -264,6 +264,9 @@ static uint8_t get_setinfo_break_count(struct torture_context *tctx)
 	if (TARGET_IS_W2K12(tctx)) {
 		return 2;
 	}
+	if (TARGET_IS_SAMBA3(tctx)) {
+		return 2;
+	}
 	return 1;
 }
 
-- 
1.7.9.5



More information about the samba-technical mailing list