The Samba-Bugzilla – Attachment 10479 Details for
Bug 10911
SMB2 leases are not yet supported.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Backports for v4-2-test part1
tmp42-01.diff.txt (text/plain), 192.77 KB, created by
Stefan Metzmacher
on 2014-12-04 01:55:17 UTC
(
hide
)
Description:
Backports for v4-2-test part1
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2014-12-04 01:55:17 UTC
Size:
192.77 KB
patch
obsolete
>From 0a50a825ffc8a59beebcada8171e26552713bc73 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Tue, 23 Sep 2014 14:08:10 -0700 >Subject: [PATCH 01/47] s3-winbindd: Allow winbindd to connect over SMB2 to > servers > >This allows SMB signing to work against many more DCs, and so improves network security. > >The default for "client max protocol" remains NT1 in the rest of the code. > >Andrew Bartlett > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 14f6256c515ff4af4f478f947ad89b7edc8743cf) >--- > docs-xml/smbdotconf/protocol/clientmaxprotocol.xml | 9 +++++++-- > lib/param/loadparm.c | 11 ++++++++++- > lib/param/param_table.c | 3 ++- > libcli/smb/smb_constants.h | 3 ++- > source3/include/proto.h | 2 ++ > source3/param/loadparm.c | 20 +++++++++++++++++++- > source3/winbindd/winbindd_cm.c | 2 +- > 7 files changed, 43 insertions(+), 7 deletions(-) > >diff --git a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml >index 6693cd3..121eeb8 100644 >--- a/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml >+++ b/docs-xml/smbdotconf/protocol/clientmaxprotocol.xml >@@ -2,6 +2,7 @@ > context="G" > type="enum" > developer="1" >+ function="_client_max_protocol" > xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> > <description> > <para>The value of the parameter (a string) is the highest >@@ -71,11 +72,15 @@ > <para>Normally this option should not be set as the automatic > negotiation phase in the SMB protocol takes care of choosing > the appropriate protocol.</para> >+ >+ <para>The value <constant>default</constant> refers to the default protocol in each >+ part of the code, currently <constant>NT1</constant> in the client tools and >+ <constant>SMB3_02</constant> in winbindd.</para> > </description> > > <related>server max protocol</related> >-<related>client mn protocol</related> >+<related>client min protocol</related> > >-<value type="default">NT1</value> >+<value type="default">default</value> > <value type="example">LANMAN1</value> > </samba:parameter> >diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c >index 56c6796..dff1ca9 100644 >--- a/lib/param/loadparm.c >+++ b/lib/param/loadparm.c >@@ -2475,7 +2475,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) > lpcfg_do_global_parameter(lp_ctx, "server min protocol", "LANMAN1"); > lpcfg_do_global_parameter(lp_ctx, "server max protocol", "SMB3"); > lpcfg_do_global_parameter(lp_ctx, "client min protocol", "CORE"); >- lpcfg_do_global_parameter(lp_ctx, "client max protocol", "NT1"); >+ lpcfg_do_global_parameter(lp_ctx, "client max protocol", "default"); > lpcfg_do_global_parameter(lp_ctx, "security", "AUTO"); > lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True"); > lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True"); >@@ -3149,6 +3149,15 @@ int lpcfg_security(struct loadparm_context *lp_ctx) > lpcfg__security(lp_ctx)); > } > >+int lpcfg_client_max_protocol(struct loadparm_context *lp_ctx) >+{ >+ int client_max_protocol = lpcfg__client_max_protocol(lp_ctx); >+ if (client_max_protocol == PROTOCOL_DEFAULT) { >+ return PROTOCOL_NT1; >+ } >+ return client_max_protocol; >+} >+ > bool lpcfg_server_signing_allowed(struct loadparm_context *lp_ctx, bool *mandatory) > { > bool allowed = true; >diff --git a/lib/param/param_table.c b/lib/param/param_table.c >index 4d0e6a9..53c299c 100644 >--- a/lib/param/param_table.c >+++ b/lib/param/param_table.c >@@ -38,6 +38,7 @@ > #endif > > static const struct enum_list enum_protocol[] = { >+ {PROTOCOL_DEFAULT, "default"}, /* the caller decides what this means */ > {PROTOCOL_SMB2_10, "SMB2"}, /* for now keep PROTOCOL_SMB2_10 */ > {PROTOCOL_SMB3_00, "SMB3"}, /* for now keep PROTOCOL_SMB3_00 */ > {PROTOCOL_SMB3_02, "SMB3_02"}, >@@ -1386,7 +1387,7 @@ struct parm_struct parm_table[] = { > .label = "client max protocol", > .type = P_ENUM, > .p_class = P_GLOBAL, >- .offset = GLOBAL_VAR(client_max_protocol), >+ .offset = GLOBAL_VAR(_client_max_protocol), > .special = NULL, > .enum_list = enum_protocol, > .flags = FLAG_ADVANCED, >diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h >index 763f4fa..f841ca9 100644 >--- a/libcli/smb/smb_constants.h >+++ b/libcli/smb/smb_constants.h >@@ -76,7 +76,8 @@ > /* protocol types. It assumes that higher protocols include lower protocols > as subsets. */ > enum protocol_types { >- PROTOCOL_NONE, >+ PROTOCOL_DEFAULT=-1, >+ PROTOCOL_NONE=0, > PROTOCOL_CORE, > PROTOCOL_COREPLUS, > PROTOCOL_LANMAN1, >diff --git a/source3/include/proto.h b/source3/include/proto.h >index eed57ff..ce23289 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -987,6 +987,8 @@ bool lp_idmap_default_range(uint32_t *low, uint32_t *high); > const char *lp_idmap_backend(const char *domain_name); > const char *lp_idmap_default_backend (void); > int lp_security(void); >+int lp_client_max_protocol(void); >+int lp_winbindd_max_protocol(void); > int lp_smb2_max_credits(void); > int lp_cups_encrypt(void); > bool lp_widelinks(int ); >diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c >index 884cc45..d2afac7 100644 >--- a/source3/param/loadparm.c >+++ b/source3/param/loadparm.c >@@ -643,7 +643,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals) > Globals.max_open_files = max_open_files(); > Globals.server_max_protocol = PROTOCOL_SMB3_00; > Globals.server_min_protocol = PROTOCOL_LANMAN1; >- Globals.client_max_protocol = PROTOCOL_NT1; >+ Globals._client_max_protocol = PROTOCOL_DEFAULT; > Globals.client_min_protocol = PROTOCOL_CORE; > Globals._security = SEC_AUTO; > Globals.encrypt_passwords = true; >@@ -4336,6 +4336,24 @@ int lp_security(void) > lp__security()); > } > >+int lp_client_max_protocol(void) >+{ >+ int client_max_protocol = lp__client_max_protocol(); >+ if (client_max_protocol == PROTOCOL_DEFAULT) { >+ return PROTOCOL_NT1; >+ } >+ return client_max_protocol; >+} >+ >+int lp_winbindd_max_protocol(void) >+{ >+ int client_max_protocol = lp__client_max_protocol(); >+ if (client_max_protocol == PROTOCOL_DEFAULT) { >+ return PROTOCOL_LATEST; >+ } >+ return client_max_protocol; >+} >+ > struct loadparm_global * get_globals(void) > { > return &Globals; >diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c >index ccbe4f5..cbce0c4 100644 >--- a/source3/winbindd/winbindd_cm.c >+++ b/source3/winbindd/winbindd_cm.c >@@ -936,7 +936,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, > > result = smbXcli_negprot((*cli)->conn, (*cli)->timeout, > lp_client_min_protocol(), >- lp_client_max_protocol()); >+ lp_winbindd_max_protocol()); > > if (!NT_STATUS_IS_OK(result)) { > DEBUG(1, ("cli_negprot failed: %s\n", nt_errstr(result))); >-- >1.9.1 > > >From 510c931dd6aec59c738e804e055d49b082197854 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 5 Nov 2014 10:12:20 -0800 >Subject: [PATCH 02/47] s4:torture: Add smb2.oplock test batch9a and raw.oplock > test batch9a > >Shows attribute(stat) access open can create a file, >and subsequent attribute(stat) opens don't break oplocks. > >Can be extended to explore more varients. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 8db5150143c4770bf2ffc40a5234f7b090ec8208) >--- > selftest/knownfail | 1 + > source4/torture/raw/oplock.c | 121 +++++++++++++++++++++++++++++++++++++++ > source4/torture/smb2/oplock.c | 128 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 250 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 6cca3dd..1c4f446 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -167,6 +167,7 @@ > ^samba4.smb2.oplock.batch1\(.*\)$ # samba 4 oplocks are a mess > ^samba4.smb2.oplock.batch6\(.*\)$ # samba 4 oplocks are a mess > ^samba4.smb2.oplock.batch9\(.*\)$ # samba 4 oplocks are a mess >+^samba4.smb2.oplock.batch9a\(.*\)$ # samba 4 oplocks are a mess > ^samba4.smb2.oplock.batch10\(.*\)$ # samba 4 oplocks are a mess > ^samba4.smb2.oplock.batch20\(.*\)$ # samba 4 oplocks are a mess > ^samba4.smb2.oplock.batch26\(.*\)$ >diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c >index a4f6a05..1d7522f 100644 >--- a/source4/torture/raw/oplock.c >+++ b/source4/torture/raw/oplock.c >@@ -1873,6 +1873,126 @@ done: > return ret; > } > >+static bool test_raw_oplock_batch9a(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) >+{ >+ const char *fname = BASEDIR "\\test_batch9a.dat"; >+ NTSTATUS status; >+ bool ret = true; >+ union smb_open io; >+ uint16_t fnum=0, fnum2=0; >+ char c = 0; >+ >+ if (!torture_setup_dir(cli1, BASEDIR)) { >+ return false; >+ } >+ >+ /* cleanup */ >+ smbcli_unlink(cli1->tree, fname); >+ >+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); >+ >+ /* >+ base ntcreatex parms >+ */ >+ io.generic.level = RAW_OPEN_NTCREATEX; >+ io.ntcreatex.in.root_fid.fnum = 0; >+ io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; >+ io.ntcreatex.in.alloc_size = 0; >+ io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; >+ io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; >+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF; >+ io.ntcreatex.in.create_options = 0; >+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; >+ io.ntcreatex.in.security_flags = 0; >+ io.ntcreatex.in.fname = fname; >+ >+ torture_comment(tctx, "BATCH9: open with attributes only can create file\n"); >+ >+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | >+ NTCREATEX_FLAGS_REQUEST_OPLOCK | >+ NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; >+ io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE; >+ status = smb_raw_open(cli1->tree, tctx, &io); >+ CHECK_STATUS(tctx, status, NT_STATUS_OK); >+ fnum = io.ntcreatex.out.file.fnum; >+ CHECK_VAL(io.ntcreatex.out.create_action, FILE_WAS_CREATED); >+ CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN); >+ >+ torture_comment(tctx, "Subsequent attributes open should not break\n"); >+ >+ ZERO_STRUCT(break_info); >+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); >+ >+ status = smb_raw_open(cli2->tree, tctx, &io); >+ CHECK_STATUS(tctx, status, NT_STATUS_OK); >+ fnum2 = io.ntcreatex.out.file.fnum; >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ CHECK_VAL(io.ntcreatex.out.create_action, FILE_WAS_OPENED); >+ CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN); >+ smbcli_close(cli2->tree, fnum2); >+ >+ torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n"); >+ >+ ZERO_STRUCT(break_info); >+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); >+ >+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | >+ NTCREATEX_FLAGS_REQUEST_OPLOCK | >+ NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; >+ io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; >+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; >+ status = smb_raw_open(cli2->tree, tctx, &io); >+ CHECK_STATUS(tctx, status, NT_STATUS_OK); >+ fnum2 = io.ntcreatex.out.file.fnum; >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 1); >+ CHECK_VAL(break_info.fnum, fnum); >+ CHECK_VAL(break_info.failures, 0); >+ CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II); >+ CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN); >+ smbcli_close(cli2->tree, fnum2); >+ >+ torture_comment(tctx, "third oplocked open should grant level2 without break\n"); >+ ZERO_STRUCT(break_info); >+ smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_given, cli1->tree); >+ smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_given, cli2->tree); >+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | >+ NTCREATEX_FLAGS_REQUEST_OPLOCK | >+ NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; >+ io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; >+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; >+ status = smb_raw_open(cli2->tree, tctx, &io); >+ CHECK_STATUS(tctx, status, NT_STATUS_OK); >+ fnum2 = io.ntcreatex.out.file.fnum; >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ CHECK_VAL(break_info.failures, 0); >+ CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN); >+ >+ ZERO_STRUCT(break_info); >+ >+ torture_comment(tctx, "write should trigger a break to none on both\n"); >+ smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1); >+ >+ /* We expect two breaks */ >+ torture_wait_for_oplock_break(tctx); >+ torture_wait_for_oplock_break(tctx); >+ >+ CHECK_VAL(break_info.count, 2); >+ CHECK_VAL(break_info.level, 0); >+ CHECK_VAL(break_info.failures, 0); >+ >+ smbcli_close(cli1->tree, fnum); >+ smbcli_close(cli2->tree, fnum2); >+ >+done: >+ smb_raw_exit(cli1->session); >+ smb_raw_exit(cli2->session); >+ smbcli_deltree(cli1->tree, BASEDIR); >+ return ret; >+} >+ > static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2) > { > const char *fname = BASEDIR "\\test_batch10.dat"; >@@ -4311,6 +4431,7 @@ struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx) > torture_suite_add_2smb_test(suite, "batch7", test_raw_oplock_batch7); > torture_suite_add_2smb_test(suite, "batch8", test_raw_oplock_batch8); > torture_suite_add_2smb_test(suite, "batch9", test_raw_oplock_batch9); >+ torture_suite_add_2smb_test(suite, "batch9a", test_raw_oplock_batch9a); > torture_suite_add_2smb_test(suite, "batch10", test_raw_oplock_batch10); > torture_suite_add_2smb_test(suite, "batch11", test_raw_oplock_batch11); > torture_suite_add_2smb_test(suite, "batch12", test_raw_oplock_batch12); >diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c >index d2a2832..be1c5eb 100644 >--- a/source4/torture/smb2/oplock.c >+++ b/source4/torture/smb2/oplock.c >@@ -1611,6 +1611,133 @@ static bool test_smb2_oplock_batch9(struct torture_context *tctx, > return ret; > } > >+static bool test_smb2_oplock_batch9a(struct torture_context *tctx, >+ struct smb2_tree *tree1, >+ struct smb2_tree *tree2) >+{ >+ const char *fname = BASEDIR "\\test_batch9a.dat"; >+ NTSTATUS status; >+ bool ret = true; >+ union smb_open io; >+ struct smb2_handle h, h1, h2, h3; >+ char c = 0; >+ >+ status = torture_smb2_testdir(tree1, BASEDIR, &h); >+ torture_assert_ntstatus_ok(tctx, status, "Error creating directory"); >+ >+ /* cleanup */ >+ smb2_util_unlink(tree1, fname); >+ >+ tree1->session->transport->oplock.handler = torture_oplock_handler; >+ tree1->session->transport->oplock.private_data = tree1; >+ >+ /* >+ base ntcreatex parms >+ */ >+ ZERO_STRUCT(io.smb2); >+ io.generic.level = RAW_OPEN_SMB2; >+ io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ io.smb2.in.alloc_size = 0; >+ io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; >+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ io.smb2.in.create_options = 0; >+ io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ io.smb2.in.security_flags = 0; >+ io.smb2.in.fname = fname; >+ >+ torture_comment(tctx, "BATCH9: open with attributes only can create " >+ "file\n"); >+ >+ io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; >+ io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH; >+ io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE | >+ SEC_FILE_WRITE_ATTRIBUTE | >+ SEC_STD_SYNCHRONIZE; >+ status = smb2_create(tree1, tctx, &(io.smb2)); >+ torture_assert_ntstatus_ok(tctx, status, "Error creating the file"); >+ h1 = io.smb2.out.file.handle; >+ CHECK_VAL(io.smb2.out.create_action, FILE_WAS_CREATED); >+ CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_BATCH); >+ >+ torture_comment(tctx, "Subsequent attributes open should not break\n"); >+ >+ ZERO_STRUCT(break_info); >+ >+ status = smb2_create(tree2, tctx, &(io.smb2)); >+ torture_assert_ntstatus_ok(tctx, status, "Incorrect status"); >+ h3 = io.smb2.out.file.handle; >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ CHECK_VAL(io.smb2.out.create_action, FILE_WAS_OPENED); >+ CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ smb2_util_close(tree2, h3); >+ >+ torture_comment(tctx, "Subsequent normal open should break oplock on " >+ "attribute only open to level II\n"); >+ >+ ZERO_STRUCT(break_info); >+ >+ io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; >+ io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH; >+ io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; >+ status = smb2_create(tree2, tctx, &(io.smb2)); >+ torture_assert_ntstatus_ok(tctx, status, "Incorrect status"); >+ h2 = io.smb2.out.file.handle; >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 1); >+ CHECK_VAL(break_info.handle.data[0], h1.data[0]); >+ CHECK_VAL(break_info.failures, 0); >+ CHECK_VAL(break_info.level, SMB2_OPLOCK_LEVEL_II); >+ CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II); >+ smb2_util_close(tree2, h2); >+ >+ torture_comment(tctx, "third oplocked open should grant level2 without " >+ "break\n"); >+ ZERO_STRUCT(break_info); >+ >+ tree2->session->transport->oplock.handler = torture_oplock_handler; >+ tree2->session->transport->oplock.private_data = tree2; >+ >+ io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED; >+ io.smb2.in.oplock_level = SMB2_OPLOCK_LEVEL_BATCH; >+ io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN; >+ status = smb2_create(tree2, tctx, &(io.smb2)); >+ torture_assert_ntstatus_ok(tctx, status, "Incorrect status"); >+ h2 = io.smb2.out.file.handle; >+ torture_wait_for_oplock_break(tctx); >+ CHECK_VAL(break_info.count, 0); >+ CHECK_VAL(break_info.failures, 0); >+ CHECK_VAL(io.smb2.out.oplock_level, SMB2_OPLOCK_LEVEL_II); >+ >+ ZERO_STRUCT(break_info); >+ >+ torture_comment(tctx, "write should trigger a break to none on both\n"); >+ tree1->session->transport->oplock.handler = >+ torture_oplock_handler_level2_to_none; >+ tree2->session->transport->oplock.handler = >+ torture_oplock_handler_level2_to_none; >+ smb2_util_write(tree2, h2, &c, 0, 1); >+ >+ /* We expect two breaks */ >+ torture_wait_for_oplock_break(tctx); >+ torture_wait_for_oplock_break(tctx); >+ >+ CHECK_VAL(break_info.count, 2); >+ CHECK_VAL(break_info.level, 0); >+ CHECK_VAL(break_info.failures, 0); >+ >+ smb2_util_close(tree1, h1); >+ smb2_util_close(tree2, h2); >+ smb2_util_close(tree1, h); >+ >+ smb2_deltree(tree1, BASEDIR); >+ return ret; >+} >+ >+ > static bool test_smb2_oplock_batch10(struct torture_context *tctx, > struct smb2_tree *tree1, > struct smb2_tree *tree2) >@@ -3836,6 +3963,7 @@ struct torture_suite *torture_smb2_oplocks_init(void) > torture_suite_add_2smb2_test(suite, "batch7", test_smb2_oplock_batch7); > torture_suite_add_2smb2_test(suite, "batch8", test_smb2_oplock_batch8); > torture_suite_add_2smb2_test(suite, "batch9", test_smb2_oplock_batch9); >+ torture_suite_add_2smb2_test(suite, "batch9a", test_smb2_oplock_batch9a); > torture_suite_add_2smb2_test(suite, "batch10", test_smb2_oplock_batch10); > torture_suite_add_2smb2_test(suite, "batch11", test_smb2_oplock_batch11); > torture_suite_add_2smb2_test(suite, "batch12", test_smb2_oplock_batch12); >-- >1.9.1 > > >From a629c80ab48e3cd8628c5d35cfd67134b5379502 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 23 Sep 2014 22:56:41 +0200 >Subject: [PATCH 03/47] libcli/smb: remember the lease_version in struct > smb2_lease > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 171cefe48fe1d312c60426c09876700a07d45547) >--- > libcli/smb/smb2_lease.c | 1 + > librpc/idl/smb2_lease_struct.idl | 1 + > 2 files changed, 2 insertions(+) > >diff --git a/libcli/smb/smb2_lease.c b/libcli/smb/smb2_lease.c >index f97f096..5e9a34d 100644 >--- a/libcli/smb/smb2_lease.c >+++ b/libcli/smb/smb2_lease.c >@@ -43,6 +43,7 @@ ssize_t smb2_lease_pull(const uint8_t *buf, size_t len, > lease->lease_state = IVAL(buf, 16); > lease->lease_flags = IVAL(buf, 20); > lease->lease_duration = BVAL(buf, 24); >+ lease->lease_version = version; > > switch (version) { > case 1: >diff --git a/librpc/idl/smb2_lease_struct.idl b/librpc/idl/smb2_lease_struct.idl >index be80d14..5ccd8a3 100644 >--- a/librpc/idl/smb2_lease_struct.idl >+++ b/librpc/idl/smb2_lease_struct.idl >@@ -28,6 +28,7 @@ interface smb2_lease_struct > uint32 lease_flags; > hyper lease_duration; /* should be 0 */ > smb2_lease_key parent_lease_key; >+ uint16 lease_version; > uint16 lease_epoch; > } smb2_lease; > }; >\ No newline at end of file >-- >1.9.1 > > >From c77b01b95bfd244825478b21f891e950c92aa373 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Mon, 22 Sep 2014 21:21:36 +0200 >Subject: [PATCH 04/47] libcli/smb: mask off > SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET for version 1 > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit a6affb7bb3ff595165e708c56ede2181f0bb570f) >--- > libcli/smb/smb2_lease.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/libcli/smb/smb2_lease.c b/libcli/smb/smb2_lease.c >index 5e9a34d..e817c34 100644 >--- a/libcli/smb/smb2_lease.c >+++ b/libcli/smb/smb2_lease.c >@@ -48,6 +48,7 @@ ssize_t smb2_lease_pull(const uint8_t *buf, size_t len, > switch (version) { > case 1: > ZERO_STRUCT(lease->parent_lease_key); >+ lease->lease_flags &= ~SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET; > lease->lease_epoch = 0; > break; > case 2: >-- >1.9.1 > > >From dcaf1e19c17621aeb197095a2d0743881de213e1 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Wed, 29 Oct 2014 13:55:16 +0100 >Subject: [PATCH 05/47] libcli/smb: add smb2_lease_key_equal() helper function > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 2fc8f761c188b1abc90df68003b05b7a098aeabe) >--- > libcli/smb/smb2_lease.c | 6 ++++++ > libcli/smb/smb2_lease.h | 2 ++ > 2 files changed, 8 insertions(+) > >diff --git a/libcli/smb/smb2_lease.c b/libcli/smb/smb2_lease.c >index e817c34..41eafc9 100644 >--- a/libcli/smb/smb2_lease.c >+++ b/libcli/smb/smb2_lease.c >@@ -87,3 +87,9 @@ bool smb2_lease_push(const struct smb2_lease *lease, uint8_t *buf, size_t len) > > return true; > } >+ >+bool smb2_lease_key_equal(const struct smb2_lease_key *k1, >+ const struct smb2_lease_key *k2) >+{ >+ return ((k1->data[0] == k2->data[0]) && (k1->data[1] == k2->data[1])); >+} >diff --git a/libcli/smb/smb2_lease.h b/libcli/smb/smb2_lease.h >index ba8178d..9db239d 100644 >--- a/libcli/smb/smb2_lease.h >+++ b/libcli/smb/smb2_lease.h >@@ -32,5 +32,7 @@ > ssize_t smb2_lease_pull(const uint8_t *buf, size_t len, > struct smb2_lease *lease); > bool smb2_lease_push(const struct smb2_lease *lease, uint8_t *buf, size_t len); >+bool smb2_lease_key_equal(const struct smb2_lease_key *k1, >+ const struct smb2_lease_key *k2); > > #endif /* _LIBCLI_SMB_SMB2_LEASE_H_ */ >-- >1.9.1 > > >From b040c40224d343ba828a5ec73ae563f08b76a894 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Tue, 4 Nov 2014 21:44:45 -0800 >Subject: [PATCH 06/47] libcli/smb: Add smb2_lease_equal() which compares > client_guids and keys. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Fri Nov 7 22:41:47 CET 2014 on sn-devel-104 > >(cherry picked from commit dbb191f35bb093ad7fc8839b3d47e508be8f6069) >--- > libcli/smb/smb2_lease.c | 8 ++++++++ > libcli/smb/smb2_lease.h | 5 +++++ > 2 files changed, 13 insertions(+) > >diff --git a/libcli/smb/smb2_lease.c b/libcli/smb/smb2_lease.c >index 41eafc9..7705256 100644 >--- a/libcli/smb/smb2_lease.c >+++ b/libcli/smb/smb2_lease.c >@@ -93,3 +93,11 @@ bool smb2_lease_key_equal(const struct smb2_lease_key *k1, > { > return ((k1->data[0] == k2->data[0]) && (k1->data[1] == k2->data[1])); > } >+ >+bool smb2_lease_equal(const struct GUID *g1, >+ const struct smb2_lease_key *k1, >+ const struct GUID *g2, >+ const struct smb2_lease_key *k2) >+{ >+ return GUID_equal(g1, g2) && smb2_lease_key_equal(k1, k2); >+} >diff --git a/libcli/smb/smb2_lease.h b/libcli/smb/smb2_lease.h >index 9db239d..2e6faf7 100644 >--- a/libcli/smb/smb2_lease.h >+++ b/libcli/smb/smb2_lease.h >@@ -23,6 +23,7 @@ > #ifndef _LIBCLI_SMB_SMB2_LEASE_H_ > #define _LIBCLI_SMB_SMB2_LEASE_H_ > >+#include "librpc/gen_ndr/ndr_misc.h" > #include "librpc/gen_ndr/smb2_lease_struct.h" > > /* >@@ -34,5 +35,9 @@ ssize_t smb2_lease_pull(const uint8_t *buf, size_t len, > bool smb2_lease_push(const struct smb2_lease *lease, uint8_t *buf, size_t len); > bool smb2_lease_key_equal(const struct smb2_lease_key *k1, > const struct smb2_lease_key *k2); >+bool smb2_lease_equal(const struct GUID *g1, >+ const struct smb2_lease_key *k1, >+ const struct GUID *g2, >+ const struct smb2_lease_key *k2); > > #endif /* _LIBCLI_SMB_SMB2_LEASE_H_ */ >-- >1.9.1 > > >From 0383d40d126f5a5510e7ba297c392d68435d35e1 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 23 Sep 2014 23:34:14 +0200 >Subject: [PATCH 07/47] s3:smbd: break oplocks to none with FILE_OVERWRITE > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 87a102189bf2d87e39dd1762fff92465aa7be5ec) >--- > source3/smbd/open.c | 1 + > 1 file changed, 1 insertion(+) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index ccea1e9..26244f6 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -1431,6 +1431,7 @@ static bool delay_for_oplock(files_struct *fsp, > > switch (create_disposition) { > case FILE_SUPERSEDE: >+ case FILE_OVERWRITE: > case FILE_OVERWRITE_IF: > break_to = NO_OPLOCK; > break; >-- >1.9.1 > > >From e446f99c41504b09e39344a5fd96721d0679e0c2 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 28 Oct 2014 15:27:09 -0700 >Subject: [PATCH 08/47] s3:smbd: move all oplock granting code to > grant_fsp_oplock_type() > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> >Pair-Programmed-With: Jeremy Allison <jra@samba.org> > >Signed-off-by: Volker Lendecke <vl@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Signed-off-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit a08b0e78220f84f87b2af1535d645a994a5c93ab) >--- > source3/smbd/open.c | 73 ++++++++++++++++++++++++++++++++--------------------- > 1 file changed, 44 insertions(+), 29 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 26244f6..945850c 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -1490,38 +1490,37 @@ static bool file_has_brlocks(files_struct *fsp) > return (brl_num_locks(br_lck) > 0); > } > >-static void grant_fsp_oplock_type(files_struct *fsp, >- struct share_mode_lock *lck, >- int oplock_request) >+static NTSTATUS grant_fsp_oplock_type(struct smb_request *req, >+ struct files_struct *fsp, >+ struct share_mode_lock *lck, >+ int oplock_request) > { > bool allow_level2 = (global_client_caps & CAP_LEVEL_II_OPLOCKS) && > lp_level2_oplocks(SNUM(fsp->conn)); > bool got_level2_oplock, got_a_none_oplock; > uint32_t i; >+ bool ok; >+ NTSTATUS status; > > /* Start by granting what the client asked for, > but ensure no SAMBA_PRIVATE bits can be set. */ > fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); > >+ if (fsp->oplock_type == NO_OPLOCK) { >+ goto type_selected; >+ } >+ > if (oplock_request & INTERNAL_OPEN_ONLY) { > /* No oplocks on internal open. */ > fsp->oplock_type = NO_OPLOCK; >- DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n", >- fsp->oplock_type, fsp_str_dbg(fsp))); >- return; >+ goto type_selected; > } > > if (lp_locking(fsp->conn->params) && file_has_brlocks(fsp)) { > DEBUG(10,("grant_fsp_oplock_type: file %s has byte range locks\n", > fsp_str_dbg(fsp))); > fsp->oplock_type = NO_OPLOCK; >- } >- >- if (is_stat_open(fsp->access_mask)) { >- /* Leave the value already set. */ >- DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n", >- fsp->oplock_type, fsp_str_dbg(fsp))); >- return; >+ goto type_selected; > } > > got_level2_oplock = false; >@@ -1555,6 +1554,23 @@ static void grant_fsp_oplock_type(files_struct *fsp, > */ > if (fsp->oplock_type == LEVEL_II_OPLOCK && !allow_level2) { > fsp->oplock_type = NO_OPLOCK; >+ goto type_selected; >+ } >+ >+ type_selected: >+ status = set_file_oplock(fsp); >+ if (!NT_STATUS_IS_OK(status)) { >+ /* >+ * Could not get the kernel oplock >+ */ >+ fsp->oplock_type = NO_OPLOCK; >+ } >+ >+ ok = set_share_mode(lck, fsp, get_current_uid(fsp->conn), >+ req ? req->mid : 0, >+ fsp->oplock_type); >+ if (!ok) { >+ return NT_STATUS_NO_MEMORY; > } > > if (fsp->oplock_type == LEVEL_II_OPLOCK && !got_level2_oplock) { >@@ -1572,6 +1588,8 @@ static void grant_fsp_oplock_type(files_struct *fsp, > > DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n", > fsp->oplock_type, fsp_str_dbg(fsp))); >+ >+ return NT_STATUS_OK; > } > > static bool request_timed_out(struct timeval request_time, >@@ -2739,8 +2757,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > } > } > >- grant_fsp_oplock_type(fsp, lck, oplock_request); >- > /* > * We have the share entry *locked*..... > */ >@@ -2800,9 +2816,18 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > } > > if (file_existed) { >- /* stat opens on existing files don't get oplocks. */ >+ /* >+ * stat opens on existing files don't get oplocks. >+ * >+ * Note that we check for stat open on the *open_access_mask*, >+ * i.e. the access mask we actually used to do the open, >+ * not the one the client asked for (which is in >+ * fsp->access_mask). This is due to the fact that >+ * FILE_OVERWRITE and FILE_OVERWRITE_IF add in O_TRUNC, >+ * which adds FILE_WRITE_DATA to open_access_mask. >+ */ > if (is_stat_open(open_access_mask)) { >- fsp->oplock_type = NO_OPLOCK; >+ oplock_request = NO_OPLOCK; > } > } > >@@ -2824,21 +2849,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > * Setup the oplock info in both the shared memory and > * file structs. > */ >- >- status = set_file_oplock(fsp); >+ status = grant_fsp_oplock_type(req, fsp, lck, oplock_request); > if (!NT_STATUS_IS_OK(status)) { >- /* >- * Could not get the kernel oplock >- */ >- fsp->oplock_type = NO_OPLOCK; >- } >- >- if (!set_share_mode(lck, fsp, get_current_uid(conn), >- req ? req->mid : 0, >- fsp->oplock_type)) { > TALLOC_FREE(lck); > fd_close(fsp); >- return NT_STATUS_NO_MEMORY; >+ return status; > } > > /* Handle strange delete on close create semantics. */ >-- >1.9.1 > > >From d13e10222aa0646c9b7f5f4185476cf97c367060 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 22 Oct 2014 17:53:01 -0700 >Subject: [PATCH 09/47] s3:smbd: Don't set fsp->oplock_type before we've > granted any oplocks. > >It's not needed, and may lead to unexpected side effects. > >grant_fsp_oplock_type() is the only place to touch this. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 1020c5942a996e3e900e2b81f9964dd61fc9c71d) >--- > source3/smbd/open.c | 3 --- > 1 file changed, 3 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 945850c..28ab434 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -2423,9 +2423,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > * the open is done. */ > fsp->posix_open = posix_open; > >- /* Ensure no SAMBA_PRIVATE bits can be set. */ >- fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); >- > if (timeval_is_zero(&request_time)) { > request_time = fsp->open_time; > } >-- >1.9.1 > > >From 5a5f50ef8a4feb67dafa4748be92f8dccea3bf2f Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 28 Oct 2014 15:27:09 -0700 >Subject: [PATCH 10/47] s3:locking: convert brl_have_read field to > brl_num_read. > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 837e29035c911f3509135252c3f423d0f56b606d) >--- > source3/locking/brlock.c | 123 +++++++++++++++++++++-------------------------- > source3/locking/proto.h | 6 +-- > source3/smbd/open.c | 15 ++---- > source3/smbd/oplock.c | 115 +++++++++++++++++++++++++++----------------- > source3/smbd/proto.h | 2 + > 5 files changed, 135 insertions(+), 126 deletions(-) > >diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c >index 1c4c4d0..b7dcb41 100644 >--- a/source3/locking/brlock.c >+++ b/source3/locking/brlock.c >@@ -47,7 +47,7 @@ struct byte_range_lock { > struct files_struct *fsp; > unsigned int num_locks; > bool modified; >- bool have_read_oplocks; >+ uint32_t num_read_oplocks; > struct lock_struct *lock_data; > struct db_record *record; > }; >@@ -82,18 +82,18 @@ struct files_struct *brl_fsp(struct byte_range_lock *brl) > return brl->fsp; > } > >-bool brl_have_read_oplocks(const struct byte_range_lock *brl) >+uint32_t brl_num_read_oplocks(const struct byte_range_lock *brl) > { >- return brl->have_read_oplocks; >+ return brl->num_read_oplocks; > } > >-void brl_set_have_read_oplocks(struct byte_range_lock *brl, >- bool have_read_oplocks) >+void brl_set_num_read_oplocks(struct byte_range_lock *brl, >+ uint32_t num_read_oplocks) > { >- DEBUG(10, ("Setting have_read_oplocks to %s\n", >- have_read_oplocks ? "true" : "false")); >+ DEBUG(10, ("Setting num_read_oplocks to %"PRIu32"\n", >+ num_read_oplocks)); > SMB_ASSERT(brl->record != NULL); /* otherwise we're readonly */ >- brl->have_read_oplocks = have_read_oplocks; >+ brl->num_read_oplocks = num_read_oplocks; > brl->modified = true; > } > >@@ -1841,7 +1841,6 @@ int brl_forall(void (*fn)(struct file_id id, struct server_id pid, > > static void byte_range_lock_flush(struct byte_range_lock *br_lck) > { >- size_t data_len; > unsigned i; > struct lock_struct *locks = br_lck->lock_data; > >@@ -1865,15 +1864,7 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck) > } > } > >- data_len = br_lck->num_locks * sizeof(struct lock_struct); >- >- if (br_lck->have_read_oplocks) { >- data_len += 1; >- } >- >- DEBUG(10, ("data_len=%d\n", (int)data_len)); >- >- if (data_len == 0) { >+ if ((br_lck->num_locks == 0) && (br_lck->num_read_oplocks == 0)) { > /* No locks - delete this entry. */ > NTSTATUS status = dbwrap_record_delete(br_lck->record); > if (!NT_STATUS_IS_OK(status)) { >@@ -1882,19 +1873,20 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck) > smb_panic("Could not delete byte range lock entry"); > } > } else { >+ size_t lock_len, data_len; > TDB_DATA data; > NTSTATUS status; > >+ lock_len = br_lck->num_locks * sizeof(struct lock_struct); >+ data_len = lock_len + sizeof(br_lck->num_read_oplocks); >+ > data.dsize = data_len; > data.dptr = talloc_array(talloc_tos(), uint8_t, data_len); > SMB_ASSERT(data.dptr != NULL); > >- memcpy(data.dptr, br_lck->lock_data, >- br_lck->num_locks * sizeof(struct lock_struct)); >- >- if (br_lck->have_read_oplocks) { >- data.dptr[data_len-1] = 1; >- } >+ memcpy(data.dptr, br_lck->lock_data, lock_len); >+ memcpy(data.dptr + lock_len, &br_lck->num_read_oplocks, >+ sizeof(br_lck->num_read_oplocks)); > > status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE); > TALLOC_FREE(data.dptr); >@@ -1917,6 +1909,32 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) > return 0; > } > >+static bool brl_parse_data(struct byte_range_lock *br_lck, TDB_DATA data) >+{ >+ size_t data_len; >+ >+ if (data.dsize == 0) { >+ return true; >+ } >+ if (data.dsize % sizeof(struct lock_struct) != >+ sizeof(br_lck->num_read_oplocks)) { >+ DEBUG(1, ("Invalid data size: %u\n", (unsigned)data.dsize)); >+ return false; >+ } >+ >+ br_lck->num_locks = data.dsize / sizeof(struct lock_struct); >+ data_len = br_lck->num_locks * sizeof(struct lock_struct); >+ >+ br_lck->lock_data = talloc_memdup(br_lck, data.dptr, data_len); >+ if (br_lck->lock_data == NULL) { >+ DEBUG(1, ("talloc_memdup failed\n")); >+ return false; >+ } >+ memcpy(&br_lck->num_read_oplocks, data.dptr + data_len, >+ sizeof(br_lck->num_read_oplocks)); >+ return true; >+} >+ > /******************************************************************* > Fetch a set of byte range lock data from the database. > Leave the record locked. >@@ -1926,16 +1944,14 @@ static int byte_range_lock_destructor(struct byte_range_lock *br_lck) > struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp) > { > TDB_DATA key, data; >- struct byte_range_lock *br_lck = talloc(mem_ctx, struct byte_range_lock); >+ struct byte_range_lock *br_lck; > >+ br_lck = talloc_zero(mem_ctx, struct byte_range_lock); > if (br_lck == NULL) { > return NULL; > } > > br_lck->fsp = fsp; >- br_lck->num_locks = 0; >- br_lck->have_read_oplocks = false; >- br_lck->modified = False; > > key.dptr = (uint8 *)&fsp->file_id; > key.dsize = sizeof(struct file_id); >@@ -1950,30 +1966,12 @@ struct byte_range_lock *brl_get_locks(TALLOC_CTX *mem_ctx, files_struct *fsp) > > data = dbwrap_record_get_value(br_lck->record); > >- br_lck->lock_data = NULL; >- >- talloc_set_destructor(br_lck, byte_range_lock_destructor); >- >- br_lck->num_locks = data.dsize / sizeof(struct lock_struct); >- >- if (br_lck->num_locks != 0) { >- br_lck->lock_data = talloc_array( >- br_lck, struct lock_struct, br_lck->num_locks); >- if (br_lck->lock_data == NULL) { >- DEBUG(0, ("malloc failed\n")); >- TALLOC_FREE(br_lck); >- return NULL; >- } >- >- memcpy(br_lck->lock_data, data.dptr, >- talloc_get_size(br_lck->lock_data)); >+ if (!brl_parse_data(br_lck, data)) { >+ TALLOC_FREE(br_lck); >+ return NULL; > } > >- DEBUG(10, ("data.dsize=%d\n", (int)data.dsize)); >- >- if ((data.dsize % sizeof(struct lock_struct)) == 1) { >- br_lck->have_read_oplocks = (data.dptr[data.dsize-1] == 1); >- } >+ talloc_set_destructor(br_lck, byte_range_lock_destructor); > > if (DEBUGLEVEL >= 10) { > unsigned int i; >@@ -1999,28 +1997,19 @@ static void brl_get_locks_readonly_parser(TDB_DATA key, TDB_DATA data, > { > struct brl_get_locks_readonly_state *state = > (struct brl_get_locks_readonly_state *)private_data; >- struct byte_range_lock *br_lock; >+ struct byte_range_lock *br_lck; > >- br_lock = talloc_pooled_object( >+ br_lck = talloc_pooled_object( > state->mem_ctx, struct byte_range_lock, 1, data.dsize); >- if (br_lock == NULL) { >+ if (br_lck == NULL) { > *state->br_lock = NULL; > return; > } >- br_lock->lock_data = (struct lock_struct *)talloc_memdup( >- br_lock, data.dptr, data.dsize); >- br_lock->num_locks = data.dsize / sizeof(struct lock_struct); >- >- if ((data.dsize % sizeof(struct lock_struct)) == 1) { >- br_lock->have_read_oplocks = (data.dptr[data.dsize-1] == 1); >- } else { >- br_lock->have_read_oplocks = false; >+ if (!brl_parse_data(br_lck, data)) { >+ *state->br_lock = NULL; >+ return; > } >- >- DEBUG(10, ("Got %d bytes, have_read_oplocks: %s\n", (int)data.dsize, >- br_lock->have_read_oplocks ? "true" : "false")); >- >- *state->br_lock = br_lock; >+ *state->br_lock = br_lck; > } > > struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) >@@ -2063,7 +2052,7 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp) > return NULL; > } > >- br_lock->have_read_oplocks = false; >+ br_lock->num_read_oplocks = 0; > br_lock->num_locks = 0; > br_lock->lock_data = NULL; > >diff --git a/source3/locking/proto.h b/source3/locking/proto.h >index 44f3ba1..8eccff8 100644 >--- a/source3/locking/proto.h >+++ b/source3/locking/proto.h >@@ -30,9 +30,9 @@ void brl_shutdown(void); > > unsigned int brl_num_locks(const struct byte_range_lock *brl); > struct files_struct *brl_fsp(struct byte_range_lock *brl); >-bool brl_have_read_oplocks(const struct byte_range_lock *brl); >-void brl_set_have_read_oplocks(struct byte_range_lock *brl, >- bool have_read_oplocks); >+uint32_t brl_num_read_oplocks(const struct byte_range_lock *brl); >+void brl_set_num_read_oplocks(struct byte_range_lock *brl, >+ uint32_t num_read_oplocks); > > NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck, > struct lock_struct *plock, >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 28ab434..1952823 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -1573,17 +1573,10 @@ static NTSTATUS grant_fsp_oplock_type(struct smb_request *req, > return NT_STATUS_NO_MEMORY; > } > >- if (fsp->oplock_type == LEVEL_II_OPLOCK && !got_level2_oplock) { >- /* >- * We're the first level2 oplock. Indicate that in brlock.tdb. >- */ >- struct byte_range_lock *brl; >- >- brl = brl_get_locks(talloc_tos(), fsp); >- if (brl != NULL) { >- brl_set_have_read_oplocks(brl, true); >- TALLOC_FREE(brl); >- } >+ ok = update_num_read_oplocks(fsp, lck); >+ if (!ok) { >+ del_share_mode(lck, fsp); >+ return NT_STATUS_INTERNAL_ERROR; > } > > DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n", >diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c >index 7935092..aa99f68 100644 >--- a/source3/smbd/oplock.c >+++ b/source3/smbd/oplock.c >@@ -148,6 +148,53 @@ static void downgrade_file_oplock(files_struct *fsp) > TALLOC_FREE(fsp->oplock_timeout); > } > >+bool update_num_read_oplocks(files_struct *fsp, struct share_mode_lock *lck) >+{ >+ struct share_mode_data *d = lck->data; >+ struct byte_range_lock *br_lck; >+ uint32_t num_read_oplocks = 0; >+ uint32_t i; >+ >+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { >+ /* >+ * If we're the only one, we don't need a brlock entry >+ */ >+ SMB_ASSERT(d->num_share_modes == 1); >+ SMB_ASSERT(EXCLUSIVE_OPLOCK_TYPE(d->share_modes[0].op_type)); >+ return true; >+ } >+ >+ for (i=0; i<d->num_share_modes; i++) { >+ struct share_mode_entry *e = &d->share_modes[i]; >+ >+ if (EXCLUSIVE_OPLOCK_TYPE(e->op_type)) { >+ num_read_oplocks += 1; >+ continue; >+ } >+ >+ if (LEVEL_II_OPLOCK_TYPE(e->op_type)) { >+ num_read_oplocks += 1; >+ continue; >+ } >+ } >+ >+ br_lck = brl_get_locks_readonly(fsp); >+ if (br_lck == NULL) { >+ return false; >+ } >+ if (brl_num_read_oplocks(br_lck) == num_read_oplocks) { >+ return true; >+ } >+ >+ br_lck = brl_get_locks(talloc_tos(), fsp); >+ if (br_lck == NULL) { >+ return false; >+ } >+ brl_set_num_read_oplocks(br_lck, num_read_oplocks); >+ TALLOC_FREE(br_lck); >+ return true; >+} >+ > /**************************************************************************** > Remove a file oplock. Copes with level II and exclusive. > Locks then unlocks the share mode lock. Client can decide to go directly >@@ -170,44 +217,6 @@ bool remove_oplock(files_struct *fsp) > return False; > } > >- if (fsp->oplock_type == LEVEL_II_OPLOCK) { >- >- /* >- * If we're the only LEVEL_II holder, we have to remove the >- * have_read_oplocks from the brlock entry >- */ >- >- struct share_mode_data *data = lck->data; >- uint32_t i, num_level2; >- >- num_level2 = 0; >- for (i=0; i<data->num_share_modes; i++) { >- if (data->share_modes[i].op_type == LEVEL_II_OPLOCK) { >- num_level2 += 1; >- } >- if (num_level2 > 1) { >- /* >- * No need to count them all... >- */ >- break; >- } >- } >- >- if (num_level2 == 1) { >- /* >- * That's only us. We are dropping that level2 oplock, >- * so remove the brlock flag. >- */ >- struct byte_range_lock *brl; >- >- brl = brl_get_locks(talloc_tos(), fsp); >- if (brl) { >- brl_set_have_read_oplocks(brl, false); >- TALLOC_FREE(brl); >- } >- } >- } >- > ret = remove_share_oplock(lck, fsp); > if (!ret) { > DEBUG(0,("remove_oplock: failed to remove share oplock for " >@@ -216,6 +225,15 @@ bool remove_oplock(files_struct *fsp) > file_id_string_tos(&fsp->file_id))); > } > release_file_oplock(fsp); >+ >+ ret = update_num_read_oplocks(fsp, lck); >+ if (!ret) { >+ DEBUG(0, ("%s: update_num_read_oplocks failed for " >+ "file %s, %s, %s\n", >+ __func__, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), >+ file_id_string_tos(&fsp->file_id))); >+ } >+ > TALLOC_FREE(lck); > return ret; > } >@@ -227,7 +245,6 @@ bool downgrade_oplock(files_struct *fsp) > { > bool ret; > struct share_mode_lock *lck; >- struct byte_range_lock *brl; > > DEBUG(10, ("downgrade_oplock called for %s\n", > fsp_str_dbg(fsp))); >@@ -245,13 +262,14 @@ bool downgrade_oplock(files_struct *fsp) > fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), > file_id_string_tos(&fsp->file_id))); > } >- > downgrade_file_oplock(fsp); > >- brl = brl_get_locks(talloc_tos(), fsp); >- if (brl != NULL) { >- brl_set_have_read_oplocks(brl, true); >- TALLOC_FREE(brl); >+ ret = update_num_read_oplocks(fsp, lck); >+ if (!ret) { >+ DEBUG(0, ("%s: update_num_read_oplocks failed for " >+ "file %s, %s, %s\n", >+ __func__, fsp_str_dbg(fsp), fsp_fnum_dbg(fsp), >+ file_id_string_tos(&fsp->file_id))); > } > > TALLOC_FREE(lck); >@@ -596,6 +614,7 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp, > struct tevent_immediate *im; > struct break_to_none_state *state; > struct byte_range_lock *brl; >+ uint32_t num_read_oplocks = 0; > > /* > * If this file is level II oplocked then we need >@@ -613,7 +632,13 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp, > } > > brl = brl_get_locks_readonly(fsp); >- if ((brl != NULL) && !brl_have_read_oplocks(brl)) { >+ if (brl != NULL) { >+ num_read_oplocks = brl_num_read_oplocks(brl); >+ } >+ >+ DEBUG(10, ("num_read_oplocks = %"PRIu32"\n", num_read_oplocks)); >+ >+ if (num_read_oplocks == 0) { > DEBUG(10, ("No read oplocks around\n")); > return; > } >diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h >index 68c2da2..1080895 100644 >--- a/source3/smbd/proto.h >+++ b/source3/smbd/proto.h >@@ -647,6 +647,8 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, > > /* The following definitions come from smbd/oplock.c */ > >+bool update_num_read_oplocks(files_struct *fsp, struct share_mode_lock *lck); >+ > void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp); > NTSTATUS set_file_oplock(files_struct *fsp); > bool remove_oplock(files_struct *fsp); >-- >1.9.1 > > >From 9476f54289b9d68100584d2e3a94c900f1cd05c9 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 23 Sep 2014 18:49:46 +0200 >Subject: [PATCH 11/47] s3:smb2_break: First test for > NT_STATUS_INVALID_OPLOCK_PROTOCOL, then for in_oplock_level being reasonable > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Wed Nov 12 00:03:34 CET 2014 on sn-devel-104 > >(cherry picked from commit 2d44498740d98edd9d09f12d35dc91d8d17e0c62) >--- > source3/smbd/smb2_break.c | 22 +++++++++++----------- > 1 file changed, 11 insertions(+), 11 deletions(-) > >diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c >index 5c079ec..4492456 100644 >--- a/source3/smbd/smb2_break.c >+++ b/source3/smbd/smb2_break.c >@@ -52,11 +52,6 @@ NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req) > > in_oplock_level = CVAL(inbody, 0x02); > >- if (in_oplock_level != SMB2_OPLOCK_LEVEL_NONE && >- in_oplock_level != SMB2_OPLOCK_LEVEL_II) { >- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); >- } >- > /* 0x03 1 bytes reserved */ > /* 0x04 4 bytes reserved */ > in_file_id_persistent = BVAL(inbody, 0x08); >@@ -67,6 +62,17 @@ NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req) > return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED); > } > >+ /* Are we awaiting a break message ? */ >+ if (in_fsp->oplock_timeout == NULL) { >+ return smbd_smb2_request_error( >+ req, NT_STATUS_INVALID_OPLOCK_PROTOCOL); >+ } >+ >+ if (in_oplock_level != SMB2_OPLOCK_LEVEL_NONE && >+ in_oplock_level != SMB2_OPLOCK_LEVEL_II) { >+ return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); >+ } >+ > subreq = smbd_smb2_oplock_break_send(req, req->sconn->ev_ctx, > req, in_fsp, in_oplock_level); > if (subreq == NULL) { >@@ -177,12 +183,6 @@ static struct tevent_req *smbd_smb2_oplock_break_send(TALLOC_CTX *mem_ctx, > fsp_str_dbg(fsp), > fsp_fnum_dbg(fsp))); > >- /* Are we awaiting a break message ? */ >- if (fsp->oplock_timeout == NULL) { >- tevent_req_nterror(req, NT_STATUS_INVALID_OPLOCK_PROTOCOL); >- return tevent_req_post(req, ev); >- } >- > if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) || > (break_to_none)) { > result = remove_oplock(fsp); >-- >1.9.1 > > >From f25df70387163256d32a92c018780ce903dc8ce0 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 26 Nov 2014 11:06:16 +0100 >Subject: [PATCH 12/47] Revert "libcli/smb: mask off > SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET for version 1" > >This reverts commit a6affb7bb3ff595165e708c56ede2181f0bb570f. > >This is not really needed. The caller should ignore this flag. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 334089c1015ca35ee37d4c9bf5da455e72c3e86e) >--- > libcli/smb/smb2_lease.c | 1 - > 1 file changed, 1 deletion(-) > >diff --git a/libcli/smb/smb2_lease.c b/libcli/smb/smb2_lease.c >index 7705256..fc641ff 100644 >--- a/libcli/smb/smb2_lease.c >+++ b/libcli/smb/smb2_lease.c >@@ -48,7 +48,6 @@ ssize_t smb2_lease_pull(const uint8_t *buf, size_t len, > switch (version) { > case 1: > ZERO_STRUCT(lease->parent_lease_key); >- lease->lease_flags &= ~SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET; > lease->lease_epoch = 0; > break; > case 2: >-- >1.9.1 > > >From 94cfbca9e9a21d874a2d9eb9c116f4a5f23ea9d5 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 13 Nov 2014 12:10:46 +0100 >Subject: [PATCH 13/47] s3:smb2_create: send interim responses after 0.5 > milliseconds > >We don't have to care about delayed NT_STATUS_SHARING_VIOLATION anymore >after the following commit: > > commit 4111fcfd4f570d39d46a0d414546ca62c7b609be > Author: Jeremy Allison <jra@samba.org> > Date: Thu May 2 11:12:47 2013 -0700 > > Only do the 1 second delay for sharing violations for SMB1, not SMB2. > > Match Windows behavior. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit fe0ad5c66884da5e7cba5c7b0d40a8c41cf6a63b) >--- > source3/smbd/smb2_create.c | 8 +------- > 1 file changed, 1 insertion(+), 7 deletions(-) > >diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c >index 48bc486..1e54801 100644 >--- a/source3/smbd/smb2_create.c >+++ b/source3/smbd/smb2_create.c >@@ -241,13 +241,7 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req) > } > tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req); > >- /* >- * For now we keep the logic that we do not send STATUS_PENDING >- * for sharing violations, so we just wait 2 seconds. >- * >- * TODO: we need more tests for this. >- */ >- return smbd_smb2_request_pending_queue(smb2req, tsubreq, 2000000); >+ return smbd_smb2_request_pending_queue(smb2req, tsubreq, 500); > } > > static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req) >-- >1.9.1 > > >From 6fe1ac6225612f4ff64ea3ff14a288389e7fcccb Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 20 Nov 2014 14:30:31 +0100 >Subject: [PATCH 14/47] s4:libcli/smb_composite: use the options on the > transport > >These are the options which really belong to the connection >and might not be the the same as the hints given from the caller. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 55750f010423b0548e9d6b8f5745d7ad5fc4b773) >--- > source4/libcli/smb_composite/connect.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/libcli/smb_composite/connect.c b/source4/libcli/smb_composite/connect.c >index 14b53e5..d87d5ec 100644 >--- a/source4/libcli/smb_composite/connect.c >+++ b/source4/libcli/smb_composite/connect.c >@@ -297,7 +297,7 @@ static NTSTATUS connect_send_negprot(struct composite_context *c, > state->subreq = smb_raw_negotiate_send(state, > state->transport->ev, > state->transport, >- io->in.options.max_protocol); >+ state->transport->options.max_protocol); > NT_STATUS_HAVE_NO_MEMORY(state->subreq); > tevent_req_set_callback(state->subreq, subreq_handler, c); > state->stage = CONNECT_NEGPROT; >-- >1.9.1 > > >From 653ab64c9f6287dd2645b06e990c156d1b313ed2 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 20 Nov 2014 14:32:40 +0100 >Subject: [PATCH 15/47] s4:libcli/raw: fix up the max_protocol value for the > current transport connection > >This allows the caller to pass PROTOCOL_DEFAULT, >which results in PROTOCOL_NT1. > >As smbcli_transport_init() is about SMB1 only we downgrade >to PROTOCOL_NT1 if a higher value (for SMB2 or SMB3) was given. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit bc83e45a19deccfb0106c9ad79b0624b1c5d1fa7) >--- > source4/libcli/raw/clitransport.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c >index f9d96b58..d0dd1f9 100644 >--- a/source4/libcli/raw/clitransport.c >+++ b/source4/libcli/raw/clitransport.c >@@ -58,6 +58,14 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock, > transport->ev = sock->event.ctx; > transport->options = *options; > >+ if (transport->options.max_protocol == PROTOCOL_DEFAULT) { >+ transport->options.max_protocol = PROTOCOL_NT1; >+ } >+ >+ if (transport->options.max_protocol > PROTOCOL_NT1) { >+ transport->options.max_protocol = PROTOCOL_NT1; >+ } >+ > TALLOC_FREE(sock->event.fde); > TALLOC_FREE(sock->event.te); > >-- >1.9.1 > > >From 50174c6a9505f332c5010b0ae5de059b86930a54 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 20 Nov 2014 14:35:38 +0100 >Subject: [PATCH 16/47] s4:libcli/smb2: allow the caller to specify a specific > value for max_protocol. > >The default is still PROTOCOL_LATEST. As smb2_connect*() is about SMB2/3 only >we upgrade to PROTOCOL_LATEST if PROTOCOL_NT1 or lower is given. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit d0a1995b934895ae9f0bbeed52772a4ef5d4b0dd) >--- > source4/libcli/smb2/connect.c | 3 ++- > source4/libcli/smb2/transport.c | 8 ++++++++ > 2 files changed, 10 insertions(+), 1 deletion(-) > >diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c >index c81bd67..9535380 100644 >--- a/source4/libcli/smb2/connect.c >+++ b/source4/libcli/smb2/connect.c >@@ -149,7 +149,8 @@ static void smb2_connect_socket_done(struct composite_context *creq) > > subreq = smbXcli_negprot_send(state, state->ev, > state->transport->conn, timeout_msec, >- PROTOCOL_SMB2_02, PROTOCOL_LATEST); >+ PROTOCOL_SMB2_02, >+ state->transport->options.max_protocol); > if (tevent_req_nomem(subreq, req)) { > return; > } >diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c >index 9b0c146..e3b2954 100644 >--- a/source4/libcli/smb2/transport.c >+++ b/source4/libcli/smb2/transport.c >@@ -55,6 +55,14 @@ struct smb2_transport *smb2_transport_init(struct smbcli_socket *sock, > transport->ev = sock->event.ctx; > transport->options = *options; > >+ if (transport->options.max_protocol == PROTOCOL_DEFAULT) { >+ transport->options.max_protocol = PROTOCOL_LATEST; >+ } >+ >+ if (transport->options.max_protocol < PROTOCOL_SMB2_02) { >+ transport->options.max_protocol = PROTOCOL_LATEST; >+ } >+ > TALLOC_FREE(sock->event.fde); > TALLOC_FREE(sock->event.te); > >-- >1.9.1 > > >From 99b554704ad8bf878682a954e3fdd2de192d2d88 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 20 Nov 2014 14:38:09 +0100 >Subject: [PATCH 17/47] s4:param: don't expand PROTOCOL_DEFAULT in > lpcfg_smbcli_options() > >We let the low-level smb1 or smb2 code assign what PROTOCOL_DEFAULT means. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit d7669ea451fa445b6ec77fa08d951fa59b08ab5f) >--- > source4/param/loadparm.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c >index 529c828..af3313f 100644 >--- a/source4/param/loadparm.c >+++ b/source4/param/loadparm.c >@@ -40,7 +40,7 @@ void lpcfg_smbcli_options(struct loadparm_context *lp_ctx, > options->signing = lpcfg_client_signing(lp_ctx); > options->request_timeout = SMB_REQUEST_TIMEOUT; > options->ntstatus_support = lpcfg_nt_status_support(lp_ctx); >- options->max_protocol = lpcfg_client_max_protocol(lp_ctx); >+ options->max_protocol = lpcfg__client_max_protocol(lp_ctx); > options->unicode = lpcfg_unicode(lp_ctx); > options->use_oplocks = true; > options->use_level2_oplocks = true; >-- >1.9.1 > > >From 1456551d58c8d9cc1e93f162c6c32b4d1bc7952d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 11 Nov 2014 19:33:13 +0100 >Subject: [PATCH 18/47] s4:libcli/smb2: add new_epoch to struct > smb2_lease_break > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 3327615c23fbfd26b572b01acfe7e1402f018a16) >--- > source4/libcli/raw/interfaces.h | 1 + > source4/libcli/smb2/transport.c | 1 + > 2 files changed, 2 insertions(+) > >diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h >index 9003c12..05f5da0 100644 >--- a/source4/libcli/raw/interfaces.h >+++ b/source4/libcli/raw/interfaces.h >@@ -57,6 +57,7 @@ struct smb2_handle { > > struct smb2_lease_break { > struct smb2_lease current_lease; >+ uint16_t new_epoch; /* only for v2 leases */ > uint32_t break_flags; > uint32_t new_lease_state; > uint32_t break_reason; /* should be 0 */ >diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c >index e3b2954..166f34b 100644 >--- a/source4/libcli/smb2/transport.c >+++ b/source4/libcli/smb2/transport.c >@@ -398,6 +398,7 @@ static void smb2_transport_break_handler(struct tevent_req *subreq) > struct smb2_lease_break lb; > > ZERO_STRUCT(lb); >+ lb.new_epoch = SVAL(body, 0x2); > lb.break_flags = SVAL(body, 0x4); > memcpy(&lb.current_lease.lease_key, body+0x8, > sizeof(struct smb2_lease_key)); >-- >1.9.1 > > >From 7ddbd00fb1d07b78c6947397f96556828ca36ba9 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 11:13:15 +0100 >Subject: [PATCH 19/47] s4:libcli/smb2: initialize ls->lease_version > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 38b0fded58f9e066ad7190f7797cdfb92d3d23ff) >--- > source4/libcli/smb2/create.c | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c >index 10fe4f7..550069a 100644 >--- a/source4/libcli/smb2/create.c >+++ b/source4/libcli/smb2/create.c >@@ -385,9 +385,11 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct > switch (io->out.blobs.blobs[i].data.length) { > case 32: > ls = &io->out.lease_response; >+ ls->lease_version = 1; > break; > case 52: > ls = &io->out.lease_response_v2; >+ ls->lease_version = 2; > break; > default: > smb2_request_destroy(req); >-- >1.9.1 > > >From 42816ea794eafd4ad0e8a8479dd8a6c55b5784f3 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 07:19:49 +0100 >Subject: [PATCH 20/47] s4:torture/smb2: skip lease tests if the server doesn't > support them > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 683b9569487bd30ecd0ba677367dbe9e0eff16c2) >--- > source4/torture/smb2/lease.c | 62 +++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 56 insertions(+), 6 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 4326958..e06faea 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -142,12 +142,14 @@ static bool test_lease_request(struct torture_context *tctx, > CHECK_LEASE(&io, "RHW", true, LEASE1); > > /* But will reject leases on directories. */ >- smb2_lease_create(&io, &ls, true, dname, LEASE2, smb2_util_lease_state("RHW")); >- status = smb2_create(tree, mem_ctx, &io); >- CHECK_STATUS(status, NT_STATUS_OK); >- CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY); >- CHECK_LEASE(&io, "", false, 0); >- smb2_util_close(tree, io.out.file.handle); >+ if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) { >+ smb2_lease_create(&io, &ls, true, dname, LEASE2, smb2_util_lease_state("RHW")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY); >+ CHECK_LEASE(&io, "", false, 0); >+ smb2_util_close(tree, io.out.file.handle); >+ } > > /* Also rejects multiple files leased under the same key. */ > smb2_lease_create(&io, &ls, true, fname2, LEASE1, smb2_util_lease_state("RHW")); >@@ -1191,6 +1193,21 @@ static bool test_lease_v2_request_parent(struct torture_context *tctx, > NTSTATUS status; > const char *fname = "lease.dat"; > bool ret = true; >+ uint32_t caps; >+ enum protocol_types protocol; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) { >+ torture_skip(tctx, "directory leases are not supported"); >+ } >+ >+ protocol = smbXcli_conn_protocol(tree->session->transport->conn); >+ if (protocol < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "v2 leases are not supported"); >+ } > > smb2_util_unlink(tree, fname); > >@@ -1230,6 +1247,7 @@ static bool test_lease_break_twice(struct torture_context *tctx, > const char *fname = "lease.dat"; > bool ret = true; > uint32_t caps; >+ enum protocol_types protocol; > > caps = smb2cli_conn_server_capabilities( > tree->session->transport->conn); >@@ -1237,6 +1255,11 @@ static bool test_lease_break_twice(struct torture_context *tctx, > torture_skip(tctx, "leases are not supported"); > } > >+ protocol = smbXcli_conn_protocol(tree->session->transport->conn); >+ if (protocol < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "v2 leases are not supported"); >+ } >+ > smb2_util_unlink(tree, fname); > > ZERO_STRUCT(break_info); >@@ -1297,6 +1320,21 @@ static bool test_lease_v2_request(struct torture_context *tctx, > const char *dnamefname = "lease.dir\\lease.dat"; > const char *dnamefname2 = "lease.dir\\lease2.dat"; > bool ret = true; >+ uint32_t caps; >+ enum protocol_types protocol; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) { >+ torture_skip(tctx, "directory leases are not supported"); >+ } >+ >+ protocol = smbXcli_conn_protocol(tree->session->transport->conn); >+ if (protocol < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "v2 leases are not supported"); >+ } > > smb2_util_unlink(tree, fname); > smb2_deltree(tree, dname); >@@ -1427,6 +1465,18 @@ static bool test_lease_v2_epoch1(struct torture_context *tctx, > const char *fname = "lease.dat"; > bool ret = true; > NTSTATUS status; >+ uint32_t caps; >+ enum protocol_types protocol; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ protocol = smbXcli_conn_protocol(tree->session->transport->conn); >+ if (protocol < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "v2 leases are not supported"); >+ } > > smb2_util_unlink(tree, fname); > >-- >1.9.1 > > >From d2c5788d1c9938de3be52ff4798d8ec7cedbb71b Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 07:23:31 +0100 >Subject: [PATCH 21/47] s4:torture/smb2: make lease tests more reliable by > calling torture_wait_for_lease_break() > >They now work against w2k8r2, w2012, w2012r2. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 34926bd4bd13ea6518273e94473fbb47b7cf565e) >--- > source4/torture/smb2/lease.c | 77 +++++++++++++++++++++++--------------------- > 1 file changed, 41 insertions(+), 36 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index e06faea..5aade0c 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -406,14 +406,35 @@ static struct { > int oplock_failures; > } break_info; > >+#define CHECK_NO_BREAK(tctx) \ >+ do { \ >+ torture_wait_for_lease_break(tctx); \ >+ CHECK_VAL(break_info.failures, 0); \ >+ CHECK_VAL(break_info.count, 0); \ >+ CHECK_VAL(break_info.oplock_failures, 0); \ >+ CHECK_VAL(break_info.oplock_count, 0); \ >+ } while(0) >+ >+#define CHECK_OPLOCK_BREAK(__brokento) \ >+ do { \ >+ torture_wait_for_lease_break(tctx); \ >+ CHECK_VAL(break_info.oplock_count, 1); \ >+ CHECK_VAL(break_info.oplock_failures, 0); \ >+ CHECK_VAL(break_info.oplock_level, \ >+ smb2_util_oplock_level(__brokento)); \ >+ break_info.held_oplock_level = break_info.oplock_level; \ >+ } while(0) >+ > #define CHECK_BREAK_INFO(__oldstate, __state, __key) \ > do { \ >+ torture_wait_for_lease_break(tctx); \ > CHECK_VAL(break_info.failures, 0); \ > CHECK_VAL(break_info.count, 1); \ > CHECK_LEASE_BREAK(&break_info.lease_break, (__oldstate), \ > (__state), (__key)); \ > if (break_info.lease_break.break_flags & \ > SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { \ >+ torture_wait_for_lease_break(tctx); \ > CHECK_LEASE_BREAK_ACK(&break_info.lease_break_ack, \ > (__state), (__key)); \ > } \ >@@ -819,9 +840,7 @@ static bool test_lease_nobreakself(struct torture_context *tctx, > /* Make sure we don't break ourselves on write */ > > status = smb2_util_write(tree, h1, &c, 0, 1); >- torture_wait_for_lease_break(tctx); >- CHECK_VAL(break_info.count, 1); >- CHECK_VAL(break_info.failures, 0); >+ CHECK_STATUS(status, NT_STATUS_OK); > CHECK_BREAK_INFO("R", "", LEASE2); > > /* Try the other way round. First, upgrade LEASE2 to R again */ >@@ -837,18 +856,14 @@ static bool test_lease_nobreakself(struct torture_context *tctx, > > ZERO_STRUCT(break_info); > status = smb2_util_write(tree, h2, &c, 0, 1); >- torture_wait_for_lease_break(tctx); >- CHECK_VAL(break_info.count, 1); >- CHECK_VAL(break_info.failures, 0); >+ CHECK_STATUS(status, NT_STATUS_OK); > CHECK_BREAK_INFO("R", "", LEASE1); > > /* .. and break LEASE2 via h1 */ > > ZERO_STRUCT(break_info); > status = smb2_util_write(tree, h1, &c, 0, 1); >- torture_wait_for_lease_break(tctx); >- CHECK_VAL(break_info.count, 1); >- CHECK_VAL(break_info.failures, 0); >+ CHECK_STATUS(status, NT_STATUS_OK); > CHECK_BREAK_INFO("R", "", LEASE2); > > done: >@@ -992,8 +1007,7 @@ static bool test_lease_oplock(struct torture_context *tctx, > if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) { > CHECK_BREAK_INFO(held, brokento, LEASE1); > } else { >- CHECK_VAL(break_info.count, 0); >- CHECK_VAL(break_info.failures, 0); >+ CHECK_NO_BREAK(tctx); > } > > smb2_util_close(tree, h); >@@ -1033,13 +1047,9 @@ static bool test_lease_oplock(struct torture_context *tctx, > CHECK_LEASE(&io, granted, true, LEASE1); > > if (smb2_util_oplock_level(held) != smb2_util_oplock_level(brokento)) { >- CHECK_VAL(break_info.oplock_count, 1); >- CHECK_VAL(break_info.oplock_failures, 0); >- CHECK_VAL(break_info.oplock_level, smb2_util_oplock_level(brokento)); >- break_info.held_oplock_level = break_info.oplock_level; >+ CHECK_OPLOCK_BREAK(brokento); > } else { >- CHECK_VAL(break_info.oplock_count, 0); >- CHECK_VAL(break_info.oplock_failures, 0); >+ CHECK_NO_BREAK(tctx); > } > > smb2_util_close(tree, h); >@@ -1141,8 +1151,7 @@ static bool test_lease_multibreak(struct torture_context *tctx, > break_info.held_oplock_level = io.out.oplock_level; > > /* Verify no breaks. */ >- CHECK_VAL(break_info.count, 0); >- CHECK_VAL(break_info.failures, 0); >+ CHECK_NO_BREAK(tctx); > > /* Open for truncate, force a break. */ > smb2_generic_create(&io, NULL, false, fname, >@@ -1165,9 +1174,7 @@ static bool test_lease_multibreak(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > > /* Verify one oplock break, one lease break. */ >- CHECK_VAL(break_info.oplock_count, 1); >- CHECK_VAL(break_info.oplock_failures, 0); >- CHECK_VAL(break_info.oplock_level, smb2_util_oplock_level("")); >+ CHECK_OPLOCK_BREAK(""); > CHECK_BREAK_INFO("R", "", LEASE1); > > done: >@@ -1384,9 +1391,7 @@ static bool test_lease_v2_request(struct torture_context *tctx, > CHECK_LEASE_V2(&io, "RHW", true, LEASE3, > SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2); > >- torture_wait_for_lease_break(tctx); >- CHECK_VAL(break_info.count, 0); >- CHECK_VAL(break_info.failures, 0); >+ CHECK_NO_BREAK(tctx); > > ZERO_STRUCT(io); > smb2_lease_v2_create_share(&io, &ls, false, dnamefname2, >@@ -1400,10 +1405,7 @@ static bool test_lease_v2_request(struct torture_context *tctx, > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); > CHECK_LEASE_V2(&io, "RHW", true, LEASE4, 0, 0); > >- torture_wait_for_lease_break(tctx); >- torture_wait_for_lease_break(tctx); > CHECK_BREAK_INFO("RH", "", LEASE2); >- torture_wait_for_lease_break(tctx); > > ZERO_STRUCT(break_info); > >@@ -1429,16 +1431,19 @@ static bool test_lease_v2_request(struct torture_context *tctx, > status = smb2_write(tree, &w); > CHECK_STATUS(status, NT_STATUS_OK); > >- smb_msleep(2000); >- torture_wait_for_lease_break(tctx); >- CHECK_VAL(break_info.count, 0); >- CHECK_VAL(break_info.failures, 0); >- >+ /* >+ * Wait 4 seconds in order to check if the write time >+ * was updated (after 2 seconds). >+ */ >+ smb_msleep(4000); >+ CHECK_NO_BREAK(tctx); >+ >+ /* >+ * only the close on the modified file break the >+ * directory lease. >+ */ > smb2_util_close(tree, h4); >- torture_wait_for_lease_break(tctx); >- torture_wait_for_lease_break(tctx); > CHECK_BREAK_INFO("RH", "", LEASE2); >- torture_wait_for_lease_break(tctx); > > done: > smb2_util_close(tree, h1); >-- >1.9.1 > > >From 5ecabad0eece3d5407f7d1cf56b21ec0fd66c141 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 07:24:16 +0100 >Subject: [PATCH 22/47] s4:torture/smb2: lease per test fnames > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 2742257be693d57c075523e2691137692aa9e34a) >--- > source4/torture/smb2/lease.c | 36 ++++++++++++++++++------------------ > 1 file changed, 18 insertions(+), 18 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 5aade0c..ef88473 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -116,10 +116,10 @@ static bool test_lease_request(struct torture_context *tctx, > struct smb2_lease ls; > struct smb2_handle h1, h2; > NTSTATUS status; >- const char *fname = "lease.dat"; >- const char *fname2 = "lease2.dat"; >- const char *sname = "lease.dat:stream"; >- const char *dname = "lease.dir"; >+ const char *fname = "lease_request.dat"; >+ const char *fname2 = "lease_request.2.dat"; >+ const char *sname = "lease_request.dat:stream"; >+ const char *dname = "lease_request.dir"; > bool ret = true; > int i; > uint32_t caps; >@@ -204,7 +204,7 @@ static bool test_lease_upgrade(struct torture_context *tctx, > struct smb2_lease ls; > struct smb2_handle h, hnew; > NTSTATUS status; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_upgrade.dat"; > bool ret = true; > uint32_t caps; > >@@ -328,7 +328,7 @@ static bool test_lease_upgrade2(struct torture_context *tctx, > NTSTATUS status; > struct smb2_create io; > struct smb2_lease ls; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_upgrade2.dat"; > bool ret = true; > int i; > uint32_t caps; >@@ -545,7 +545,7 @@ static bool test_lease_upgrade3(struct torture_context *tctx, > NTSTATUS status; > struct smb2_create io; > struct smb2_lease ls; >- const char *fname = "upgrade3.dat"; >+ const char *fname = "lease_upgrade3.dat"; > bool ret = true; > int i; > uint32_t caps; >@@ -711,7 +711,7 @@ static bool test_lease_break(struct torture_context *tctx, > struct smb2_lease ls; > struct smb2_handle h, h2, h3; > NTSTATUS status; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_break.dat"; > bool ret = true; > int i; > uint32_t caps; >@@ -803,7 +803,7 @@ static bool test_lease_nobreakself(struct torture_context *tctx, > struct smb2_lease ls; > struct smb2_handle h1, h2; > NTSTATUS status; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_nobreakself.dat"; > bool ret = true; > uint32_t caps; > char c = 0; >@@ -958,7 +958,7 @@ static bool test_lease_oplock(struct torture_context *tctx, > struct smb2_lease ls; > struct smb2_handle h, h2; > NTSTATUS status; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_oplock.dat"; > bool ret = true; > int i; > uint32_t caps; >@@ -1079,7 +1079,7 @@ static bool test_lease_multibreak(struct torture_context *tctx, > struct smb2_handle h, h2, h3; > struct smb2_write w; > NTSTATUS status; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_multibreak.dat"; > bool ret = true; > uint32_t caps; > >@@ -1198,7 +1198,7 @@ static bool test_lease_v2_request_parent(struct torture_context *tctx, > struct smb2_handle h1; > uint64_t parent = LEASE2; > NTSTATUS status; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_v2_request_parent.dat"; > bool ret = true; > uint32_t caps; > enum protocol_types protocol; >@@ -1251,7 +1251,7 @@ static bool test_lease_break_twice(struct torture_context *tctx, > struct smb2_lease ls; > struct smb2_handle h1; > NTSTATUS status; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_break_twice.dat"; > bool ret = true; > uint32_t caps; > enum protocol_types protocol; >@@ -1322,10 +1322,10 @@ static bool test_lease_v2_request(struct torture_context *tctx, > struct smb2_handle h1, h2, h3, h4, h5; > struct smb2_write w; > NTSTATUS status; >- const char *fname = "lease.dat"; >- const char *dname = "lease.dir"; >- const char *dnamefname = "lease.dir\\lease.dat"; >- const char *dnamefname2 = "lease.dir\\lease2.dat"; >+ const char *fname = "lease_v2_request.dat"; >+ const char *dname = "lease_v2_request.dir"; >+ const char *dnamefname = "lease_v2_request.dir\\lease.dat"; >+ const char *dnamefname2 = "lease_v2_request.dir\\lease2.dat"; > bool ret = true; > uint32_t caps; > enum protocol_types protocol; >@@ -1467,7 +1467,7 @@ static bool test_lease_v2_epoch1(struct torture_context *tctx, > struct smb2_create io; > struct smb2_lease ls; > struct smb2_handle h; >- const char *fname = "lease.dat"; >+ const char *fname = "lease_v2_epoch1.dat"; > bool ret = true; > NTSTATUS status; > uint32_t caps; >-- >1.9.1 > > >From 347935fdf21f1b4ff43f89733950ed6a210c6efd Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 17:00:44 +0100 >Subject: [PATCH 23/47] s4:torture/smb2: verify lease_flags in > CHECK_LEASE_BREAK() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 8fa2fb7dde10640ded645d8180d441012dbad155) >--- > source4/torture/smb2/lease.c | 12 ++++++++++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index ef88473..999c9d4 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -377,10 +377,18 @@ static bool test_lease_upgrade2(struct torture_context *tctx, > > #define CHECK_LEASE_BREAK(__lb, __oldstate, __state, __key) \ > do { \ >- CHECK_VAL((__lb)->new_lease_state, smb2_util_lease_state(__state)); \ >- CHECK_VAL((__lb)->current_lease.lease_state, smb2_util_lease_state(__oldstate)); \ >+ uint16_t __new = smb2_util_lease_state(__state); \ >+ uint16_t __old = smb2_util_lease_state(__oldstate); \ >+ CHECK_VAL((__lb)->new_lease_state, __new); \ >+ CHECK_VAL((__lb)->current_lease.lease_state, __old); \ > CHECK_VAL((__lb)->current_lease.lease_key.data[0], (__key)); \ > CHECK_VAL((__lb)->current_lease.lease_key.data[1], ~(__key)); \ >+ if (__old & (SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE)) { \ >+ CHECK_VAL((__lb)->break_flags, \ >+ SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED); \ >+ } else { \ >+ CHECK_VAL((__lb)->break_flags, 0); \ >+ } \ > } while(0) > > #define CHECK_LEASE_BREAK_ACK(__lba, __state, __key) \ >-- >1.9.1 > > >From 020683b9145ee9743168b3e03a26f2527fcd39a7 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 11 Nov 2014 19:35:07 +0100 >Subject: [PATCH 24/47] s4:torture/smb2: always verify the v2 lease epoch. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit c0f2b46d69dc7e729bac766785b26a1911a80825) >--- > source4/torture/smb2/lease.c | 115 ++++++++++++++++++++++++++----------------- > 1 file changed, 71 insertions(+), 44 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 999c9d4..d10dcc5 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -53,6 +53,7 @@ > > #define CHECK_LEASE(__io, __state, __oplevel, __key) \ > do { \ >+ CHECK_VAL((__io)->out.lease_response.lease_version, 1); \ > if (__oplevel) { \ > CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \ > CHECK_VAL((__io)->out.lease_response.lease_key.data[0], (__key)); \ >@@ -67,10 +68,12 @@ > \ > CHECK_VAL((__io)->out.lease_response.lease_flags, 0); \ > CHECK_VAL((__io)->out.lease_response.lease_duration, 0); \ >+ CHECK_VAL((__io)->out.lease_response.lease_epoch, 0); \ > } while(0) > >-#define CHECK_LEASE_V2(__io, __state, __oplevel, __key, __flags, __parent) \ >+#define CHECK_LEASE_V2(__io, __state, __oplevel, __key, __flags, __parent, __epoch) \ > do { \ >+ CHECK_VAL((__io)->out.lease_response_v2.lease_version, 2); \ > if (__oplevel) { \ > CHECK_VAL((__io)->out.oplock_level, SMB2_OPLOCK_LEVEL_LEASE); \ > CHECK_VAL((__io)->out.lease_response_v2.lease_key.data[0], (__key)); \ >@@ -89,6 +92,7 @@ > CHECK_VAL((__io)->out.lease_response_v2.parent_lease_key.data[1], ~(__parent)); \ > } \ > CHECK_VAL((__io)->out.lease_response_v2.lease_duration, 0); \ >+ CHECK_VAL((__io)->out.lease_response_v2.lease_epoch, (__epoch)); \ > } while(0) > > static const uint64_t LEASE1 = 0xBADC0FFEE0DDF00Dull; >@@ -147,7 +151,7 @@ static bool test_lease_request(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY); >- CHECK_LEASE(&io, "", false, 0); >+ CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); > smb2_util_close(tree, io.out.file.handle); > } > >@@ -403,6 +407,7 @@ static bool test_lease_upgrade2(struct torture_context *tctx, > > static struct { > struct smb2_lease_break lease_break; >+ struct smb2_transport *lease_transport; > struct smb2_lease_break_ack lease_break_ack; > int count; > int failures; >@@ -433,7 +438,7 @@ static struct { > break_info.held_oplock_level = break_info.oplock_level; \ > } while(0) > >-#define CHECK_BREAK_INFO(__oldstate, __state, __key) \ >+#define _CHECK_BREAK_INFO(__oldstate, __state, __key) \ > do { \ > torture_wait_for_lease_break(tctx); \ > CHECK_VAL(break_info.failures, 0); \ >@@ -448,6 +453,20 @@ static struct { > } \ > } while(0) > >+#define CHECK_BREAK_INFO(__oldstate, __state, __key) \ >+ do { \ >+ _CHECK_BREAK_INFO(__oldstate, __state, __key); \ >+ CHECK_VAL(break_info.lease_break.new_epoch, 0); \ >+ } while(0) >+ >+#define CHECK_BREAK_INFO_V2(__transport, __oldstate, __state, __key, __epoch) \ >+ do { \ >+ _CHECK_BREAK_INFO(__oldstate, __state, __key); \ >+ CHECK_VAL(break_info.lease_break.new_epoch, __epoch); \ >+ CHECK_VAL((uintptr_t)break_info.lease_transport, \ >+ (uintptr_t)__transport); \ >+ } while(0) >+ > static void torture_lease_break_callback(struct smb2_request *req) > { > NTSTATUS status; >@@ -468,6 +487,7 @@ static bool torture_lease_handler(struct smb2_transport *transport, > struct smb2_lease_break_ack io; > struct smb2_request *req; > >+ break_info.lease_transport = transport; > break_info.lease_break = *lb; > break_info.count++; > >@@ -765,8 +785,7 @@ static bool test_lease_break(struct torture_context *tctx, > if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) { > CHECK_BREAK_INFO(held, brokento, LEASE1); > } else { >- CHECK_VAL(break_info.count, 0); >- CHECK_VAL(break_info.failures, 0); >+ CHECK_NO_BREAK(tctx); > } > > ZERO_STRUCT(break_info); >@@ -1233,14 +1252,15 @@ static bool test_lease_v2_request_parent(struct torture_context *tctx, > smb2_util_share_access("RWD"), > LEASE1, &parent, > smb2_util_lease_state("RHW"), >- 0); >+ 0x11); > > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h1 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); > CHECK_LEASE_V2(&io, "RHW", true, LEASE1, >- SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2); >+ SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2, >+ ls.lease_epoch + 1); > > done: > smb2_util_close(tree, h1); >@@ -1256,7 +1276,8 @@ static bool test_lease_break_twice(struct torture_context *tctx, > { > TALLOC_CTX *mem_ctx = talloc_new(tctx); > struct smb2_create io; >- struct smb2_lease ls; >+ struct smb2_lease ls1; >+ struct smb2_lease ls2; > struct smb2_handle h1; > NTSTATUS status; > const char *fname = "lease_break_twice.dat"; >@@ -1279,17 +1300,16 @@ static bool test_lease_break_twice(struct torture_context *tctx, > > ZERO_STRUCT(break_info); > ZERO_STRUCT(io); >- ZERO_STRUCT(ls); > > smb2_lease_v2_create_share( >- &io, &ls, false, fname, smb2_util_share_access("RWD"), >- LEASE1, NULL, smb2_util_lease_state("RWH"), 0); >+ &io, &ls1, false, fname, smb2_util_share_access("RWD"), >+ LEASE1, NULL, smb2_util_lease_state("RWH"), 0x11); > > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h1 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0); >+ CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1); > > tree->session->transport->lease.handler = torture_lease_handler; > tree->session->transport->lease.private_data = tree; >@@ -1297,22 +1317,25 @@ static bool test_lease_break_twice(struct torture_context *tctx, > ZERO_STRUCT(break_info); > > smb2_lease_v2_create_share( >- &io, &ls, false, fname, smb2_util_share_access("R"), >- LEASE2, NULL, smb2_util_lease_state("RWH"), 0); >+ &io, &ls2, false, fname, smb2_util_share_access("R"), >+ LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22); > > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); >- CHECK_BREAK_INFO("RWH", "RW", LEASE1); >+ CHECK_BREAK_INFO_V2(tree->session->transport, >+ "RWH", "RW", LEASE1, ls1.lease_epoch + 2); > > smb2_lease_v2_create_share( >- &io, &ls, false, fname, smb2_util_share_access("RWD"), >- LEASE2, NULL, smb2_util_lease_state("RWH"), 0); >+ &io, &ls2, false, fname, smb2_util_share_access("RWD"), >+ LEASE2, NULL, smb2_util_lease_state("RWH"), 0x22); > > ZERO_STRUCT(break_info); > > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); >- CHECK_BREAK_INFO("RW", "R", LEASE1); >+ CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1); >+ CHECK_BREAK_INFO_V2(tree->session->transport, >+ "RW", "R", LEASE1, ls1.lease_epoch + 3); > > done: > smb2_util_close(tree, h1); >@@ -1326,7 +1349,7 @@ static bool test_lease_v2_request(struct torture_context *tctx, > { > TALLOC_CTX *mem_ctx = talloc_new(tctx); > struct smb2_create io; >- struct smb2_lease ls; >+ struct smb2_lease ls1, ls2, ls2t, ls3, ls4; > struct smb2_handle h1, h2, h3, h4, h5; > struct smb2_write w; > NTSTATUS status; >@@ -1362,73 +1385,75 @@ static bool test_lease_v2_request(struct torture_context *tctx, > ZERO_STRUCT(break_info); > > ZERO_STRUCT(io); >- smb2_lease_v2_create_share(&io, &ls, false, fname, >+ smb2_lease_v2_create_share(&io, &ls1, false, fname, > smb2_util_share_access("RWD"), > LEASE1, NULL, > smb2_util_lease_state("RHW"), >- 0); >+ 0x11); > > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h1 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0); >+ CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1.lease_epoch + 1); > > ZERO_STRUCT(io); >- smb2_lease_v2_create_share(&io, &ls, true, dname, >+ smb2_lease_v2_create_share(&io, &ls2, true, dname, > smb2_util_share_access("RWD"), > LEASE2, NULL, > smb2_util_lease_state("RHW"), >- 0); >+ 0x22); > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h2 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_DIRECTORY); >- CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0); >+ CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch + 1); > > ZERO_STRUCT(io); >- smb2_lease_v2_create_share(&io, &ls, false, dnamefname, >+ smb2_lease_v2_create_share(&io, &ls3, false, dnamefname, > smb2_util_share_access("RWD"), > LEASE3, &LEASE2, > smb2_util_lease_state("RHW"), >- 0); >+ 0x33); > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h3 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); > CHECK_LEASE_V2(&io, "RHW", true, LEASE3, >- SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2); >+ SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET, LEASE2, >+ ls3.lease_epoch + 1); > > CHECK_NO_BREAK(tctx); > > ZERO_STRUCT(io); >- smb2_lease_v2_create_share(&io, &ls, false, dnamefname2, >+ smb2_lease_v2_create_share(&io, &ls4, false, dnamefname2, > smb2_util_share_access("RWD"), > LEASE4, NULL, > smb2_util_lease_state("RHW"), >- 0); >+ 0x44); > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h4 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE_V2(&io, "RHW", true, LEASE4, 0, 0); >+ CHECK_LEASE_V2(&io, "RHW", true, LEASE4, 0, 0, ls4.lease_epoch + 1); > >- CHECK_BREAK_INFO("RH", "", LEASE2); >+ CHECK_BREAK_INFO_V2(tree->session->transport, >+ "RH", "", LEASE2, ls2.lease_epoch + 2); > > ZERO_STRUCT(break_info); > > ZERO_STRUCT(io); >- smb2_lease_v2_create_share(&io, &ls, true, dname, >+ smb2_lease_v2_create_share(&io, &ls2t, true, dname, > smb2_util_share_access("RWD"), > LEASE2, NULL, > smb2_util_lease_state("RHW"), >- 0); >+ 0x222); > io.in.create_disposition = NTCREATEX_DISP_OPEN; > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h5 = io.out.file.handle; > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_DIRECTORY); >- CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0); >+ CHECK_LEASE_V2(&io, "RH", true, LEASE2, 0, 0, ls2.lease_epoch+3); > smb2_util_close(tree, h5); > > ZERO_STRUCT(w); >@@ -1451,7 +1476,9 @@ static bool test_lease_v2_request(struct torture_context *tctx, > * directory lease. > */ > smb2_util_close(tree, h4); >- CHECK_BREAK_INFO("RH", "", LEASE2); >+ >+ CHECK_BREAK_INFO_V2(tree->session->transport, >+ "RH", "", LEASE2, ls2.lease_epoch+4); > > done: > smb2_util_close(tree, h1); >@@ -1505,26 +1532,26 @@ static bool test_lease_v2_epoch1(struct torture_context *tctx, > smb2_util_share_access("RWD"), > LEASE1, NULL, > smb2_util_lease_state("RHW"), >- 0); >- ls.lease_epoch = 0x4711; >- >+ 0x4711); > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0); >- CHECK_VAL(io.out.lease_response_v2.lease_epoch, ls.lease_epoch + 1); >+ CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls.lease_epoch + 1); > smb2_util_close(tree, h); > smb2_util_unlink(tree, fname); > >- ls.lease_state = smb2_util_lease_state("RH"); >+ smb2_lease_v2_create_share(&io, &ls, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, NULL, >+ smb2_util_lease_state("RHW"), >+ 0x11); > > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE_V2(&io, "RH", true, LEASE1, 0, 0); >- CHECK_VAL(io.out.lease_response_v2.lease_epoch, ls.lease_epoch + 1); >+ CHECK_LEASE_V2(&io, "RWH", true, LEASE1, 0, 0, ls.lease_epoch + 1); > smb2_util_close(tree, h); > > done: >-- >1.9.1 > > >From 1bb44e1e78a081a94cfd801eec2cb5c1fee300ca Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 09:15:58 +0100 >Subject: [PATCH 25/47] s4:torture/smb2: don't check the lease break connection > against samba3 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit a9d46264ab3eb53cf4a70edf4e5dad2fe6d86e6c) >--- > source4/torture/smb2/lease.c | 7 +++++-- > 1 file changed, 5 insertions(+), 2 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index d10dcc5..2c5cbd0 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -25,6 +25,7 @@ > #include "libcli/smb2/smb2_calls.h" > #include "torture/torture.h" > #include "torture/smb2/proto.h" >+#include "torture/util.h" > #include "libcli/smb/smbXcli_base.h" > > #define CHECK_VAL(v, correct) do { \ >@@ -463,8 +464,10 @@ static struct { > do { \ > _CHECK_BREAK_INFO(__oldstate, __state, __key); \ > CHECK_VAL(break_info.lease_break.new_epoch, __epoch); \ >- CHECK_VAL((uintptr_t)break_info.lease_transport, \ >- (uintptr_t)__transport); \ >+ if (!TARGET_IS_SAMBA3(tctx)) { \ >+ CHECK_VAL((uintptr_t)break_info.lease_transport, \ >+ (uintptr_t)__transport); \ >+ } \ > } while(0) > > static void torture_lease_break_callback(struct smb2_request *req) >-- >1.9.1 > > >From ca9280609486831bcced6e702a0bbd133da99c25 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 15:41:50 +0100 >Subject: [PATCH 26/47] s4:torture/smb2: pass the expected flags to > CHECK_LEASE() > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 90c886e9656a1360ffdb8eaa80ad2b6c987f73ef) >--- > source4/torture/smb2/lease.c | 52 ++++++++++++++++++++++---------------------- > 1 file changed, 26 insertions(+), 26 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 2c5cbd0..d81ddd3 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -52,7 +52,7 @@ > CHECK_VAL((__io)->out.reserved2, 0); \ > } while(0) > >-#define CHECK_LEASE(__io, __state, __oplevel, __key) \ >+#define CHECK_LEASE(__io, __state, __oplevel, __key, __flags) \ > do { \ > CHECK_VAL((__io)->out.lease_response.lease_version, 1); \ > if (__oplevel) { \ >@@ -67,7 +67,7 @@ > CHECK_VAL((__io)->out.lease_response.lease_state, 0); \ > } \ > \ >- CHECK_VAL((__io)->out.lease_response.lease_flags, 0); \ >+ CHECK_VAL((__io)->out.lease_response.lease_flags, (__flags)); \ > CHECK_VAL((__io)->out.lease_response.lease_duration, 0); \ > CHECK_VAL((__io)->out.lease_response.lease_epoch, 0); \ > } while(0) >@@ -144,7 +144,7 @@ static bool test_lease_request(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h1 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RHW", true, LEASE1); >+ CHECK_LEASE(&io, "RHW", true, LEASE1, 0); > > /* But will reject leases on directories. */ > if (!(caps & SMB2_CAP_DIRECTORY_LEASING)) { >@@ -167,7 +167,7 @@ static bool test_lease_request(struct torture_context *tctx, > h2 = io.out.file.handle; > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RHW", true, LEASE2); >+ CHECK_LEASE(&io, "RHW", true, LEASE2, 0); > smb2_util_close(tree, h2); > > smb2_util_close(tree, h1); >@@ -184,7 +184,7 @@ static bool test_lease_request(struct torture_context *tctx, > h2 = io.out.file.handle; > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, request_results[i][1], true, LEASE1); >+ CHECK_LEASE(&io, request_results[i][1], true, LEASE1, 0); > smb2_util_close(tree, io.out.file.handle); > } > >@@ -225,7 +225,7 @@ static bool test_lease_upgrade(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RH", true, LEASE1); >+ CHECK_LEASE(&io, "RH", true, LEASE1, 0); > h = io.out.file.handle; > > /* Upgrades (sidegrades?) to RW leave us with an RH. */ >@@ -233,7 +233,7 @@ static bool test_lease_upgrade(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RH", true, LEASE1); >+ CHECK_LEASE(&io, "RH", true, LEASE1, 0); > hnew = io.out.file.handle; > > smb2_util_close(tree, hnew); >@@ -243,7 +243,7 @@ static bool test_lease_upgrade(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RHW", true, LEASE1); >+ CHECK_LEASE(&io, "RHW", true, LEASE1, 0); > hnew = io.out.file.handle; > > smb2_util_close(tree, h); >@@ -254,7 +254,7 @@ static bool test_lease_upgrade(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RHW", true, LEASE1); >+ CHECK_LEASE(&io, "RHW", true, LEASE1, 0); > hnew = io.out.file.handle; > > smb2_util_close(tree, hnew); >@@ -353,7 +353,7 @@ static bool test_lease_upgrade2(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, t.initial, true, LEASE1); >+ CHECK_LEASE(&io, t.initial, true, LEASE1, 0); > h = io.out.file.handle; > > /* Upgrade. */ >@@ -361,7 +361,7 @@ static bool test_lease_upgrade2(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, t.expected, true, LEASE1); >+ CHECK_LEASE(&io, t.expected, true, LEASE1, 0); > hnew = io.out.file.handle; > > smb2_util_close(tree, hnew); >@@ -603,7 +603,7 @@ static bool test_lease_upgrade3(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, t.held1, true, LEASE1); >+ CHECK_LEASE(&io, t.held1, true, LEASE1, 0); > h = io.out.file.handle; > > /* grab second lease */ >@@ -611,7 +611,7 @@ static bool test_lease_upgrade3(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, t.held2, true, LEASE2); >+ CHECK_LEASE(&io, t.held2, true, LEASE2, 0); > h2 = io.out.file.handle; > > /* no break has happened */ >@@ -623,7 +623,7 @@ static bool test_lease_upgrade3(struct torture_context *tctx, > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, t.upgraded_to, true, LEASE1); >+ CHECK_LEASE(&io, t.upgraded_to, true, LEASE1, 0); > hnew = io.out.file.handle; > > /* no break has happened */ >@@ -775,7 +775,7 @@ static bool test_lease_break(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, held, true, LEASE1); >+ CHECK_LEASE(&io, held, true, LEASE1, 0); > > /* Possibly contend lease. */ > smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state(contend)); >@@ -783,7 +783,7 @@ static bool test_lease_break(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h2 = io.out.file.handle; > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, granted, true, LEASE2); >+ CHECK_LEASE(&io, granted, true, LEASE2, 0); > > if (smb2_util_lease_state(held) != smb2_util_lease_state(brokento)) { > CHECK_BREAK_INFO(held, brokento, LEASE1); >@@ -802,7 +802,7 @@ static bool test_lease_break(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h3 = io.out.file.handle; > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, brokento, true, LEASE1); >+ CHECK_LEASE(&io, brokento, true, LEASE1, 0); > CHECK_VAL(break_info.count, 0); > CHECK_VAL(break_info.failures, 0); > >@@ -853,14 +853,14 @@ static bool test_lease_nobreakself(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h1 = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "R", true, LEASE1); >+ CHECK_LEASE(&io, "R", true, LEASE1, 0); > > smb2_lease_create(&io, &ls, false, fname, LEASE2, > smb2_util_lease_state("R")); > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h2 = io.out.file.handle; >- CHECK_LEASE(&io, "R", true, LEASE2); >+ CHECK_LEASE(&io, "R", true, LEASE2, 0); > > ZERO_STRUCT(break_info); > >@@ -879,7 +879,7 @@ static bool test_lease_nobreakself(struct torture_context *tctx, > smb2_util_lease_state("R")); > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); >- CHECK_LEASE(&io, "R", true, LEASE2); >+ CHECK_LEASE(&io, "R", true, LEASE2, 0); > smb2_util_close(tree, io.out.file.handle); > > /* Now break LEASE1 via h2 */ >@@ -1023,7 +1023,7 @@ static bool test_lease_oplock(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, held, true, LEASE1); >+ CHECK_LEASE(&io, held, true, LEASE1, 0); > > /* Does an oplock contend the lease? */ > smb2_oplock_create(&io, fname, smb2_util_oplock_level(contend)); >@@ -1074,7 +1074,7 @@ static bool test_lease_oplock(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h2 = io.out.file.handle; > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, granted, true, LEASE1); >+ CHECK_LEASE(&io, granted, true, LEASE1, 0); > > if (smb2_util_oplock_level(held) != smb2_util_oplock_level(brokento)) { > CHECK_OPLOCK_BREAK(brokento); >@@ -1133,14 +1133,14 @@ static bool test_lease_multibreak(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h = io.out.file.handle; > CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RH", true, LEASE1); >+ CHECK_LEASE(&io, "RH", true, LEASE1, 0); > > smb2_lease_create(&io, &ls, false, fname, LEASE1, smb2_util_lease_state("RHW")); > status = smb2_create(tree, mem_ctx, &io); > CHECK_STATUS(status, NT_STATUS_OK); > h2 = io.out.file.handle; > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RHW", true, LEASE1); >+ CHECK_LEASE(&io, "RHW", true, LEASE1, 0); > > /* Contend with LEASE2. */ > smb2_lease_create(&io, &ls, false, fname, LEASE2, smb2_util_lease_state("RHW")); >@@ -1148,7 +1148,7 @@ static bool test_lease_multibreak(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h3 = io.out.file.handle; > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "RH", true, LEASE2); >+ CHECK_LEASE(&io, "RH", true, LEASE2, 0); > > /* Verify that we were only sent one break. */ > CHECK_BREAK_INFO("RHW", "RH", LEASE1); >@@ -1169,7 +1169,7 @@ static bool test_lease_multibreak(struct torture_context *tctx, > CHECK_STATUS(status, NT_STATUS_OK); > h = io.out.file.handle; > CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >- CHECK_LEASE(&io, "R", true, LEASE1); >+ CHECK_LEASE(&io, "R", true, LEASE1, 0); > > /* Grab a level-II oplock. */ > smb2_oplock_create(&io, fname, smb2_util_oplock_level("s")); >-- >1.9.1 > > >From a44fd172e0dc8d1c7e60224a8c702ec5fc3fa525 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Tue, 11 Nov 2014 19:35:59 +0100 >Subject: [PATCH 27/47] s4:torture/smb2: add smb2.lease.[v2_]complex1 tests > >These tests verify the lease state is consistent between two connections >with the same client_guid. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 45c98b8069f6b94115616d7fddef515c76d7767e) >--- > source4/torture/smb2/lease.c | 273 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 273 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index d81ddd3..ac20946 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -1563,6 +1563,277 @@ done: > return ret; > } > >+static bool test_lease_complex1(struct torture_context *tctx, >+ struct smb2_tree *tree1a) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1; >+ struct smb2_create io2; >+ struct smb2_lease ls1; >+ struct smb2_lease ls2; >+ struct smb2_handle h, h2, h3; >+ struct smb2_write w; >+ NTSTATUS status; >+ const char *fname = "lease_complex1.dat"; >+ bool ret = true; >+ uint32_t caps; >+ struct smb2_tree *tree1b = NULL; >+ struct smbcli_options options1; >+ >+ options1 = tree1a->session->transport->options; >+ >+ caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ tree1a->session->transport->lease.handler = torture_lease_handler; >+ tree1a->session->transport->lease.private_data = tree1a; >+ tree1a->session->transport->oplock.handler = torture_oplock_handler; >+ tree1a->session->transport->oplock.private_data = tree1a; >+ >+ /* create a new connection (same client_guid) */ >+ if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) { >+ torture_warning(tctx, "couldn't reconnect, bailing\n"); >+ ret = false; >+ goto done; >+ } >+ >+ tree1b->session->transport->lease.handler = torture_lease_handler; >+ tree1b->session->transport->lease.private_data = tree1b; >+ tree1b->session->transport->oplock.handler = torture_oplock_handler; >+ tree1b->session->transport->oplock.private_data = tree1b; >+ >+ smb2_util_unlink(tree1a, fname); >+ >+ ZERO_STRUCT(break_info); >+ >+ /* Grab R lease over connection 1a */ >+ smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state("R")); >+ status = smb2_create(tree1a, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "R", true, LEASE1, 0); >+ >+ /* Upgrade to RWH over connection 1b */ >+ ls1.lease_state = smb2_util_lease_state("RWH"); >+ status = smb2_create(tree1b, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RHW", true, LEASE1, 0); >+ >+ /* close over connection 1b */ >+ status = smb2_util_close(tree1b, h2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ /* Contend with LEASE2. */ >+ smb2_lease_create(&io2, &ls2, false, fname, LEASE2, smb2_util_lease_state("RHW")); >+ status = smb2_create(tree1b, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h3 = io2.out.file.handle; >+ CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io2, "RH", true, LEASE2, 0); >+ >+ /* Verify that we were only sent one break. */ >+ CHECK_BREAK_INFO("RHW", "RH", LEASE1); >+ >+ /* again RH over connection 1b doesn't change the epoch */ >+ ls1.lease_state = smb2_util_lease_state("RH"); >+ status = smb2_create(tree1b, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RH", true, LEASE1, 0); >+ >+ /* close over connection 1b */ >+ status = smb2_util_close(tree1b, h2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(w); >+ w.in.file.handle = h; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 4096); >+ memset(w.in.data.data, 'o', w.in.data.length); >+ status = smb2_write(tree1a, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ ls2.lease_epoch += 1; >+ CHECK_BREAK_INFO("RH", "", LEASE2); >+ >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(w); >+ w.in.file.handle = h3; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 4096); >+ memset(w.in.data.data, 'o', w.in.data.length); >+ status = smb2_write(tree1b, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ ls1.lease_epoch += 1; >+ CHECK_BREAK_INFO("RH", "", LEASE1); >+ >+ done: >+ smb2_util_close(tree1a, h); >+ smb2_util_close(tree1b, h2); >+ smb2_util_close(tree1b, h3); >+ >+ smb2_util_unlink(tree1a, fname); >+ >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+static bool test_lease_v2_complex1(struct torture_context *tctx, >+ struct smb2_tree *tree1a) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1; >+ struct smb2_create io2; >+ struct smb2_lease ls1; >+ struct smb2_lease ls2; >+ struct smb2_handle h, h2, h3; >+ struct smb2_write w; >+ NTSTATUS status; >+ const char *fname = "lease_v2_complex1.dat"; >+ bool ret = true; >+ uint32_t caps; >+ enum protocol_types protocol; >+ struct smb2_tree *tree1b = NULL; >+ struct smbcli_options options1; >+ >+ options1 = tree1a->session->transport->options; >+ >+ caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ protocol = smbXcli_conn_protocol(tree1a->session->transport->conn); >+ if (protocol < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "v2 leases are not supported"); >+ } >+ >+ tree1a->session->transport->lease.handler = torture_lease_handler; >+ tree1a->session->transport->lease.private_data = tree1a; >+ tree1a->session->transport->oplock.handler = torture_oplock_handler; >+ tree1a->session->transport->oplock.private_data = tree1a; >+ >+ /* create a new connection (same client_guid) */ >+ if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) { >+ torture_warning(tctx, "couldn't reconnect, bailing\n"); >+ ret = false; >+ goto done; >+ } >+ >+ tree1b->session->transport->lease.handler = torture_lease_handler; >+ tree1b->session->transport->lease.private_data = tree1b; >+ tree1b->session->transport->oplock.handler = torture_oplock_handler; >+ tree1b->session->transport->oplock.private_data = tree1b; >+ >+ smb2_util_unlink(tree1a, fname); >+ >+ ZERO_STRUCT(break_info); >+ >+ /* Grab R lease over connection 1a */ >+ smb2_lease_v2_create(&io1, &ls1, false, fname, LEASE1, NULL, >+ smb2_util_lease_state("R"), 0x4711); >+ status = smb2_create(tree1a, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ ls1.lease_epoch += 1; >+ CHECK_LEASE_V2(&io1, "R", true, LEASE1, >+ 0, 0, ls1.lease_epoch); >+ >+ /* Upgrade to RWH over connection 1b */ >+ ls1.lease_state = smb2_util_lease_state("RWH"); >+ status = smb2_create(tree1b, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ ls1.lease_epoch += 1; >+ CHECK_LEASE_V2(&io1, "RHW", true, LEASE1, >+ 0, 0, ls1.lease_epoch); >+ >+ /* close over connection 1b */ >+ status = smb2_util_close(tree1b, h2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ /* Contend with LEASE2. */ >+ smb2_lease_v2_create(&io2, &ls2, false, fname, LEASE2, NULL, >+ smb2_util_lease_state("RWH"), 0x11); >+ status = smb2_create(tree1b, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h3 = io2.out.file.handle; >+ CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ ls2.lease_epoch += 1; >+ CHECK_LEASE_V2(&io2, "RH", true, LEASE2, >+ 0, 0, ls2.lease_epoch); >+ >+ /* Verify that we were only sent one break. */ >+ ls1.lease_epoch += 1; >+ CHECK_BREAK_INFO_V2(tree1a->session->transport, >+ "RHW", "RH", LEASE1, ls1.lease_epoch); >+ >+ /* again RH over connection 1b doesn't change the epoch */ >+ ls1.lease_state = smb2_util_lease_state("RH"); >+ status = smb2_create(tree1b, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE_V2(&io1, "RH", true, LEASE1, >+ 0, 0, ls1.lease_epoch); >+ >+ /* close over connection 1b */ >+ status = smb2_util_close(tree1b, h2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(w); >+ w.in.file.handle = h; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 4096); >+ memset(w.in.data.data, 'o', w.in.data.length); >+ status = smb2_write(tree1a, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ ls2.lease_epoch += 1; >+ CHECK_BREAK_INFO_V2(tree1a->session->transport, >+ "RH", "", LEASE2, ls2.lease_epoch); >+ >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(w); >+ w.in.file.handle = h3; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 4096); >+ memset(w.in.data.data, 'o', w.in.data.length); >+ status = smb2_write(tree1b, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ ls1.lease_epoch += 1; >+ CHECK_BREAK_INFO_V2(tree1a->session->transport, >+ "RH", "", LEASE1, ls1.lease_epoch); >+ >+ done: >+ smb2_util_close(tree1a, h); >+ smb2_util_close(tree1b, h2); >+ smb2_util_close(tree1b, h3); >+ >+ smb2_util_unlink(tree1a, fname); >+ >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ > struct torture_suite *torture_smb2_lease_init(void) > { > struct torture_suite *suite = >@@ -1579,10 +1850,12 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "break", test_lease_break); > torture_suite_add_1smb2_test(suite, "oplock", test_lease_oplock); > torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak); >+ torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); > torture_suite_add_1smb2_test(suite, "v2_request", test_lease_v2_request); > torture_suite_add_1smb2_test(suite, "v2_epoch1", test_lease_v2_epoch1); >+ torture_suite_add_1smb2_test(suite, "v2_complex1", test_lease_v2_complex1); > > suite->description = talloc_strdup(suite, "SMB2-LEASE tests"); > >-- >1.9.1 > > >From 12b952de4535b2668906856a51ed6fa2edd1f3a7 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 09:53:45 +0100 >Subject: [PATCH 28/47] s4:torture/smb2: add smb2.lease.v2_epoch[2|3] tests > >They demonstrate that the lease version (v1 or v2) is selected >by the first open. All following opens using the other version >still get the lease version of the first open. > >This implies that the server has to remember the lease version >more globaly. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit c18c84ca6ca04815e8ffedb3d6f8abadad06500b) >--- > source4/torture/smb2/lease.c | 210 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 210 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index ac20946..14ce739 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -1563,6 +1563,214 @@ done: > return ret; > } > >+static bool test_lease_v2_epoch2(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io; >+ struct smb2_lease ls1v2, ls1v2t, ls1v1; >+ struct smb2_handle hv2 = {}, hv1 = {}; >+ const char *fname = "lease_v2_epoch2.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ enum protocol_types protocol; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ protocol = smbXcli_conn_protocol(tree->session->transport->conn); >+ if (protocol < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "v2 leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_v2_create_share(&io, &ls1v2, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, NULL, >+ smb2_util_lease_state("R"), >+ 0x4711); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv2 = io.out.file.handle; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE_V2(&io, "R", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_create_share(&io, &ls1v1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RH")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv1 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE_V2(&io, "RH", true, LEASE1, 0, 0, ls1v2.lease_epoch + 2); >+ >+ smb2_util_close(tree, hv2); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_v2_create_share(&io, &ls1v2t, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, NULL, >+ smb2_util_lease_state("RHW"), >+ 0x11); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv2 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 3); >+ >+ smb2_util_close(tree, hv2); >+ >+ smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv2 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ CHECK_BREAK_INFO_V2(tree->session->transport, >+ "RWH", "RH", LEASE1, ls1v2.lease_epoch + 4); >+ >+ smb2_util_close(tree, hv2); >+ smb2_util_close(tree, hv1); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_create_share(&io, &ls1v1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RHW")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv1 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RHW", true, LEASE1, 0); >+ >+ smb2_util_close(tree, hv1); >+ >+done: >+ smb2_util_close(tree, hv2); >+ smb2_util_close(tree, hv1); >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ >+static bool test_lease_v2_epoch3(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io; >+ struct smb2_lease ls1v1 = {}, ls1v1t = {},ls1v2 = {}; >+ struct smb2_handle hv1 = {}, hv2 = {}; >+ const char *fname = "lease_v2_epoch3.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ enum protocol_types protocol; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ protocol = smbXcli_conn_protocol(tree->session->transport->conn); >+ if (protocol < PROTOCOL_SMB3_00) { >+ torture_skip(tctx, "v2 leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_create_share(&io, &ls1v1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("R")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv1 = io.out.file.handle; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "R", true, LEASE1, 0); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_v2_create_share(&io, &ls1v2, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, NULL, >+ smb2_util_lease_state("RW"), >+ 0x4711); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv2 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RW", true, LEASE1, 0); >+ >+ smb2_util_close(tree, hv1); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_create_share(&io, &ls1v1t, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv1 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RWH", true, LEASE1, 0); >+ >+ smb2_util_close(tree, hv1); >+ >+ smb2_oplock_create(&io, fname, SMB2_OPLOCK_LEVEL_NONE); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv1 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ CHECK_BREAK_INFO("RWH", "RH", LEASE1); >+ >+ smb2_util_close(tree, hv1); >+ smb2_util_close(tree, hv2); >+ >+ ZERO_STRUCT(io); >+ smb2_lease_v2_create_share(&io, &ls1v2, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, NULL, >+ smb2_util_lease_state("RWH"), >+ 0x4711); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ hv2 = io.out.file.handle; >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE_V2(&io, "RHW", true, LEASE1, 0, 0, ls1v2.lease_epoch + 1); >+ smb2_util_close(tree, hv2); >+ >+done: >+ smb2_util_close(tree, hv2); >+ smb2_util_close(tree, hv1); >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -1855,6 +2063,8 @@ struct torture_suite *torture_smb2_lease_init(void) > test_lease_v2_request_parent); > torture_suite_add_1smb2_test(suite, "v2_request", test_lease_v2_request); > torture_suite_add_1smb2_test(suite, "v2_epoch1", test_lease_v2_epoch1); >+ torture_suite_add_1smb2_test(suite, "v2_epoch2", test_lease_v2_epoch2); >+ torture_suite_add_1smb2_test(suite, "v2_epoch3", test_lease_v2_epoch3); > torture_suite_add_1smb2_test(suite, "v2_complex1", test_lease_v2_complex1); > > suite->description = talloc_strdup(suite, "SMB2-LEASE tests"); >-- >1.9.1 > > >From 1e70b66bea69655e13a04774b70aa0d9d1aed26f Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 15:43:56 +0100 >Subject: [PATCH 29/47] s4:torture/smb2: make it possible to skip the automatic > ack of lease breaks. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 0c239d32094f8cc20bd36b55a4d08f57d04bd263) >--- > source4/torture/smb2/lease.c | 13 ++++++++++--- > 1 file changed, 10 insertions(+), 3 deletions(-) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 14ce739..b9df9ba 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -406,9 +406,10 @@ static bool test_lease_upgrade2(struct torture_context *tctx, > CHECK_VAL((__lba)->out.lease.lease_duration, 0); \ > } while(0) > >-static struct { >+static struct torture_lease_break { > struct smb2_lease_break lease_break; > struct smb2_transport *lease_transport; >+ bool lease_skip_ack; > struct smb2_lease_break_ack lease_break_ack; > int count; > int failures; >@@ -446,8 +447,10 @@ static struct { > CHECK_VAL(break_info.count, 1); \ > CHECK_LEASE_BREAK(&break_info.lease_break, (__oldstate), \ > (__state), (__key)); \ >- if (break_info.lease_break.break_flags & \ >- SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { \ >+ if (!break_info.lease_skip_ack && \ >+ (break_info.lease_break.break_flags & \ >+ SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED)) \ >+ { \ > torture_wait_for_lease_break(tctx); \ > CHECK_LEASE_BREAK_ACK(&break_info.lease_break_ack, \ > (__state), (__key)); \ >@@ -494,6 +497,10 @@ static bool torture_lease_handler(struct smb2_transport *transport, > break_info.lease_break = *lb; > break_info.count++; > >+ if (break_info.lease_skip_ack) { >+ return true; >+ } >+ > if (lb->break_flags & SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { > ZERO_STRUCT(io); > io.in.lease.lease_key = lb->current_lease.lease_key; >-- >1.9.1 > > >From e20ccc7513e8de84d2beb8f64f7b2be24eb8480d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 15:43:56 +0100 >Subject: [PATCH 30/47] s4:torture/smb2: smb2.lease.breaking1 test > >This demonstrates a race case where the client reuses a lease, >while the server already sent a break. > >The open succeeds with SMB2_LEASE_FLAG_BREAK_IN_PROGRESS being set. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit a7a59b16a4920181fd0e2484c24b448ff8642e88) >--- > source4/torture/smb2/lease.c | 108 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 108 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index b9df9ba..5678436 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -1778,6 +1778,113 @@ done: > return ret; > } > >+static bool test_lease_breaking1(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1 = {}; >+ struct smb2_create io2 = {}; >+ struct smb2_lease ls1 = {}; >+ struct smb2_handle h1a = {}; >+ struct smb2_handle h1b = {}; >+ struct smb2_handle h2 = {}; >+ struct smb2_request *req2 = NULL; >+ struct smb2_lease_break_ack ack = {}; >+ const char *fname = "lease_breaking1.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ /* >+ * we defer acking the lease break. >+ */ >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1a = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, 0); >+ >+ /* >+ * a conflicting open is blocked until we ack the >+ * lease break >+ */ >+ smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE); >+ req2 = smb2_create_send(tree, &io2); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ >+ /* >+ * we got the lease break, but defer the ack. >+ */ >+ CHECK_BREAK_INFO("RWH", "RH", LEASE1); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ack.in.lease.lease_state = >+ break_info.lease_break.new_lease_state; >+ ZERO_STRUCT(break_info); >+ >+ /* >+ * a open using the same lease key is still works, >+ * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS >+ */ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1b = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS); >+ smb2_util_close(tree, h1b); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ /* >+ * We ack the lease break. >+ */ >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1); >+ >+ torture_assert(tctx, req2->cancel.can_cancel, >+ "req2 can_cancel"); >+ >+ status = smb2_create_recv(req2, tctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ CHECK_NO_BREAK(tctx); >+done: >+ smb2_util_close(tree, h1a); >+ smb2_util_close(tree, h1b); >+ smb2_util_close(tree, h2); >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -2065,6 +2172,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "break", test_lease_break); > torture_suite_add_1smb2_test(suite, "oplock", test_lease_oplock); > torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak); >+ torture_suite_add_1smb2_test(suite, "breaking1", test_lease_breaking1); > torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); >-- >1.9.1 > > >From 11c88c5e13d29336cff25622dd6373283204e96b Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 15 Nov 2014 11:58:01 +0100 >Subject: [PATCH 31/47] s4:torture/smb2: smb2.lease.breaking2 test > >This demonstrates that a conflicting open with NTCREATEX_DISP_OVERWRITE >breaks a lease to NONE. > >It also shows which error codes are generated for unexpected lease break acks. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 5a652dbb92231183070b2d139d3459be8fd89439) >--- > source4/torture/smb2/lease.c | 152 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 152 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 5678436..b694dd8 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -1885,6 +1885,157 @@ done: > return ret; > } > >+static bool test_lease_breaking2(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1 = {}; >+ struct smb2_create io2 = {}; >+ struct smb2_lease ls1 = {}; >+ struct smb2_handle h1a = {}; >+ struct smb2_handle h1b = {}; >+ struct smb2_handle h2 = {}; >+ struct smb2_request *req2 = NULL; >+ struct smb2_lease_break_ack ack = {}; >+ const char *fname = "lease_breaking2.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ /* >+ * we defer acking the lease break. >+ */ >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1a = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, 0); >+ >+ /* >+ * a conflicting open is blocked until we ack the >+ * lease break >+ */ >+ smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE); >+ io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE; >+ req2 = smb2_create_send(tree, &io2); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ >+ /* >+ * we got the lease break, but defer the ack. >+ */ >+ CHECK_BREAK_INFO("RWH", "", LEASE1); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ZERO_STRUCT(break_info); >+ >+ /* >+ * a open using the same lease key is still works, >+ * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS >+ */ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1b = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS); >+ smb2_util_close(tree, h1b); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ /* >+ * We ack the lease break. >+ */ >+ ack.in.lease.lease_state = >+ SMB2_LEASE_READ | SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED); >+ >+ ack.in.lease.lease_state = >+ SMB2_LEASE_READ | SMB2_LEASE_WRITE; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED); >+ >+ ack.in.lease.lease_state = >+ SMB2_LEASE_WRITE | SMB2_LEASE_HANDLE; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED); >+ >+ ack.in.lease.lease_state = >+ SMB2_LEASE_READ | SMB2_LEASE_HANDLE; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED); >+ >+ ack.in.lease.lease_state = SMB2_LEASE_WRITE; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED); >+ >+ ack.in.lease.lease_state = SMB2_LEASE_HANDLE; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED); >+ >+ ack.in.lease.lease_state = SMB2_LEASE_READ; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_REQUEST_NOT_ACCEPTED); >+ >+ /* Try again with the correct state this time. */ >+ ack.in.lease.lease_state = SMB2_LEASE_NONE;; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1); >+ >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL); >+ >+ torture_assert(tctx, req2->cancel.can_cancel, >+ "req2 can_cancel"); >+ >+ status = smb2_create_recv(req2, tctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ /* Get state of the original handle. */ >+ smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state("")); >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE(&io1, "", true, LEASE1, 0); >+ smb2_util_close(tree, io1.out.file.handle); >+ >+done: >+ smb2_util_close(tree, h1a); >+ smb2_util_close(tree, h1b); >+ smb2_util_close(tree, h2); >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -2173,6 +2324,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "oplock", test_lease_oplock); > torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak); > torture_suite_add_1smb2_test(suite, "breaking1", test_lease_breaking1); >+ torture_suite_add_1smb2_test(suite, "breaking2", test_lease_breaking2); > torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); >-- >1.9.1 > > >From e284ab1a816085e43c0817bbec90359b0a50ef07 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 12 Nov 2014 15:43:56 +0100 >Subject: [PATCH 32/47] s4:torture/smb2: smb2.lease.breaking3 test > >This demonstrates a race case where the client reuses a lease, >while the server already sent a break. > >The open succeeds with SMB2_LEASE_FLAG_BREAK_IN_PROGRESS being set. > >This is more complex that smb2.lease.breaking[1-2] as it generates breaks >from RWH => RH => R => NONE. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 8d16a2e36762f6da825106798689c96aff95437f) >--- > source4/torture/smb2/lease.c | 189 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 189 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index b694dd8..76715e7 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -2036,6 +2036,194 @@ done: > return ret; > } > >+static bool test_lease_breaking3(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1 = {}; >+ struct smb2_create io2 = {}; >+ struct smb2_create io3 = {}; >+ struct smb2_lease ls1 = {}; >+ struct smb2_handle h1a = {}; >+ struct smb2_handle h1b = {}; >+ struct smb2_handle h2 = {}; >+ struct smb2_handle h3 = {}; >+ struct smb2_request *req2 = NULL; >+ struct smb2_request *req3 = NULL; >+ struct torture_lease_break break_info_tmp = {}; >+ struct smb2_lease_break_ack ack = {}; >+ const char *fname = "lease_breaking3.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ /* >+ * we defer acking the lease break. >+ */ >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1a = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, 0); >+ >+ /* >+ * a conflicting open is blocked until we ack the >+ * lease break >+ */ >+ smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE); >+ req2 = smb2_create_send(tree, &io2); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ >+ /* >+ * we got the lease break, but defer the ack. >+ */ >+ CHECK_BREAK_INFO("RWH", "RH", LEASE1); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ /* >+ * a open using the same lease key is still works, >+ * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS >+ */ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1b = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS); >+ smb2_util_close(tree, h1b); >+ >+ /* >+ * a conflicting open with NTCREATEX_DISP_OVERWRITE >+ * doesn't trigger an immediate lease break to none. >+ */ >+ break_info_tmp = break_info; >+ ZERO_STRUCT(break_info); >+ smb2_oplock_create(&io3, fname, SMB2_OPLOCK_LEVEL_NONE); >+ io3.in.create_disposition = NTCREATEX_DISP_OVERWRITE; >+ req3 = smb2_create_send(tree, &io3); >+ torture_assert(tctx, req3 != NULL, "smb2_create_send"); >+ CHECK_NO_BREAK(tctx); >+ break_info = break_info_tmp; >+ >+ torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending"); >+ >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ack.in.lease.lease_state = >+ break_info.lease_break.new_lease_state; >+ ZERO_STRUCT(break_info); >+ >+ /* >+ * a open using the same lease key is still works, >+ * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS >+ */ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1b = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS); >+ smb2_util_close(tree, h1b); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ /* >+ * We ack the lease break, but defer acking the next break (to "R") >+ */ >+ break_info.lease_skip_ack = true; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE_BREAK_ACK(&ack, "RH", LEASE1); >+ >+ /* >+ * We got an additional break downgrading to just "R" >+ * while we defer the ack. >+ */ >+ CHECK_BREAK_INFO("RH", "R", LEASE1); >+ >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ack.in.lease.lease_state = >+ break_info.lease_break.new_lease_state; >+ ZERO_STRUCT(break_info); >+ >+ /* >+ * a open using the same lease key is still works, >+ * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS >+ */ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1b = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS); >+ smb2_util_close(tree, h1b); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ torture_assert(tctx, req3->state == SMB2_REQUEST_RECV, "req3 pending"); >+ >+ /* >+ * We ack the downgrade to "R" and get an immediate break to none >+ */ >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE_BREAK_ACK(&ack, "R", LEASE1); >+ >+ /* >+ * We get the downgrade to none. >+ */ >+ CHECK_BREAK_INFO("R", "", LEASE1); >+ >+ torture_assert(tctx, req2->cancel.can_cancel, >+ "req2 can_cancel"); >+ torture_assert(tctx, req3->cancel.can_cancel, >+ "req3 can_cancel"); >+ >+ ZERO_STRUCT(break_info); >+ >+ status = smb2_create_recv(req2, tctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ status = smb2_create_recv(req3, tctx, &io3); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h3 = io3.out.file.handle; >+ CHECK_CREATED(&io3, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io3.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ CHECK_NO_BREAK(tctx); >+done: >+ smb2_util_close(tree, h1a); >+ smb2_util_close(tree, h1b); >+ smb2_util_close(tree, h2); >+ smb2_util_close(tree, h3); >+ >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -2325,6 +2513,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "multibreak", test_lease_multibreak); > torture_suite_add_1smb2_test(suite, "breaking1", test_lease_breaking1); > torture_suite_add_1smb2_test(suite, "breaking2", test_lease_breaking2); >+ torture_suite_add_1smb2_test(suite, "breaking3", test_lease_breaking3); > torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); >-- >1.9.1 > > >From d2b64b8c6d1fcec11536d490718eb616c58aedb2 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Sat, 15 Nov 2014 11:58:01 +0100 >Subject: [PATCH 33/47] s4:torture/smb2: smb2.lease.breaking4 test > >This demonstrates that a confliciting open with NTCREATEX_DISP_OVERWRITE >isn't delayed by a "RH" lease, even if a lease is in 'breaking' mode. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit b3a985ab6662cacb2ac399c667b48e03c0bd1bfe) >--- > source4/torture/smb2/lease.c | 146 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 146 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 76715e7..dff8a11 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -2224,6 +2224,151 @@ done: > return ret; > } > >+static bool test_lease_breaking4(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1 = {}; >+ struct smb2_create io2 = {}; >+ struct smb2_create io3 = {}; >+ struct smb2_lease ls1 = {}; >+ struct smb2_lease ls1t = {}; >+ struct smb2_handle h1 = {}; >+ struct smb2_handle h2 = {}; >+ struct smb2_handle h3 = {}; >+ struct smb2_request *req2 = NULL; >+ struct torture_lease_break break_info_tmp = {}; >+ struct smb2_lease_break_ack ack = {}; >+ const char *fname = "lease_breaking4.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ /* >+ * we defer acking the lease break. >+ */ >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RH")); >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1 = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RH", true, LEASE1, 0); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ /* >+ * a conflicting open is *not* blocked until we ack the >+ * lease break >+ */ >+ smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE); >+ io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE; >+ req2 = smb2_create_send(tree, &io2); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ >+ /* >+ * We got a break from RH to NONE, we're supported to ack >+ * this downgrade >+ */ >+ CHECK_BREAK_INFO("RH", "", LEASE1); >+ >+ break_info_tmp = break_info; >+ ZERO_STRUCT(break_info); >+ CHECK_NO_BREAK(tctx); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done"); >+ >+ status = smb2_create_recv(req2, tctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ smb2_util_close(tree, h2); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ /* >+ * a conflicting open is *not* blocked until we ack the >+ * lease break, even if the lease is in breaking state. >+ */ >+ smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE); >+ io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE; >+ req2 = smb2_create_send(tree, &io2); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done"); >+ >+ status = smb2_create_recv(req2, tctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ smb2_util_close(tree, h2); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ /* >+ * We now ask the server about the current lease state >+ * which should still be "RH", but with >+ * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS. >+ */ >+ smb2_lease_create_share(&io3, &ls1t, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("")); >+ status = smb2_create(tree, mem_ctx, &io3); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h3 = io3.out.file.handle; >+ CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io3, "RH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS); >+ >+ /* >+ * We finally ack the lease break... >+ */ >+ CHECK_NO_BREAK(tctx); >+ break_info = break_info_tmp; >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ack.in.lease.lease_state = >+ break_info.lease_break.new_lease_state; >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1); >+ >+ CHECK_NO_BREAK(tctx); >+ >+done: >+ smb2_util_close(tree, h1); >+ smb2_util_close(tree, h2); >+ smb2_util_close(tree, h3); >+ >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -2514,6 +2659,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "breaking1", test_lease_breaking1); > torture_suite_add_1smb2_test(suite, "breaking2", test_lease_breaking2); > torture_suite_add_1smb2_test(suite, "breaking3", test_lease_breaking3); >+ torture_suite_add_1smb2_test(suite, "breaking4", test_lease_breaking4); > torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); >-- >1.9.1 > > >From 7a9d877a5f258608c2a42b3c9704f7ef81ba80fc Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 26 Nov 2014 10:25:45 +0100 >Subject: [PATCH 34/47] s4:torture/smb2: smb2.lease.breaking5 test > >This is like breaking4, but with an initial "R" lease instead >of "RH". > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 6494597c0451944e2599736af116d6838e6aac4e) >--- > source4/torture/smb2/lease.c | 120 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 120 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index dff8a11..ff10d5c 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -2369,6 +2369,125 @@ done: > return ret; > } > >+static bool test_lease_breaking5(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1 = {}; >+ struct smb2_create io2 = {}; >+ struct smb2_create io3 = {}; >+ struct smb2_lease ls1 = {}; >+ struct smb2_lease ls1t = {}; >+ struct smb2_handle h1 = {}; >+ struct smb2_handle h2 = {}; >+ struct smb2_handle h3 = {}; >+ struct smb2_request *req2 = NULL; >+ struct torture_lease_break break_info_tmp = {}; >+ struct smb2_lease_break_ack ack = {}; >+ const char *fname = "lease_breaking5.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ /* >+ * we defer acking the lease break. >+ */ >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("R")); >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1 = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "R", true, LEASE1, 0); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ /* >+ * a conflicting open is *not* blocked until we ack the >+ * lease break >+ */ >+ smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE); >+ io2.in.create_disposition = NTCREATEX_DISP_OVERWRITE; >+ req2 = smb2_create_send(tree, &io2); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ >+ /* >+ * We got a break from RH to NONE, we're supported to ack >+ * this downgrade >+ */ >+ CHECK_BREAK_INFO("R", "", LEASE1); >+ >+ break_info_tmp = break_info; >+ ZERO_STRUCT(break_info); >+ CHECK_NO_BREAK(tctx); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_DONE, "req2 done"); >+ >+ status = smb2_create_recv(req2, tctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, TRUNCATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ /* >+ * We now ask the server about the current lease state >+ * which should still be "RH", but with >+ * SMB2_LEASE_FLAG_BREAK_IN_PROGRESS. >+ */ >+ smb2_lease_create_share(&io3, &ls1t, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("")); >+ status = smb2_create(tree, mem_ctx, &io3); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h3 = io3.out.file.handle; >+ CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io3, "", true, LEASE1, 0); >+ >+ /* >+ * We send an ack without without being asked. >+ */ >+ CHECK_NO_BREAK(tctx); >+ break_info = break_info_tmp; >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ack.in.lease.lease_state = >+ break_info.lease_break.new_lease_state; >+ ZERO_STRUCT(break_info); >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL); >+ >+ CHECK_NO_BREAK(tctx); >+ >+done: >+ smb2_util_close(tree, h1); >+ smb2_util_close(tree, h2); >+ smb2_util_close(tree, h3); >+ >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -2660,6 +2779,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "breaking2", test_lease_breaking2); > torture_suite_add_1smb2_test(suite, "breaking3", test_lease_breaking3); > torture_suite_add_1smb2_test(suite, "breaking4", test_lease_breaking4); >+ torture_suite_add_1smb2_test(suite, "breaking5", test_lease_breaking5); > torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); >-- >1.9.1 > > >From d8613c211d1dbd2103f9828dee24bb2459ee39dd Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 26 Nov 2014 14:00:24 +0100 >Subject: [PATCH 35/47] s4:torture/smb2: smb2.lease.breaking6 test > >The client is allowed to downgrade a lease to a lower value >than required. > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit ea25f0d32a045e30d69aab4d84b15cf13a6e32ea) >--- > source4/torture/smb2/lease.c | 108 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 108 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index ff10d5c..5e788e1 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -2488,6 +2488,113 @@ done: > return ret; > } > >+static bool test_lease_breaking6(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1 = {}; >+ struct smb2_create io2 = {}; >+ struct smb2_lease ls1 = {}; >+ struct smb2_handle h1a = {}; >+ struct smb2_handle h1b = {}; >+ struct smb2_handle h2 = {}; >+ struct smb2_request *req2 = NULL; >+ struct smb2_lease_break_ack ack = {}; >+ const char *fname = "lease_breaking6.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ /* >+ * we defer acking the lease break. >+ */ >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1a = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, 0); >+ >+ /* >+ * a conflicting open is blocked until we ack the >+ * lease break >+ */ >+ smb2_oplock_create(&io2, fname, SMB2_OPLOCK_LEVEL_NONE); >+ req2 = smb2_create_send(tree, &io2); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ >+ /* >+ * we got the lease break, but defer the ack. >+ */ >+ CHECK_BREAK_INFO("RWH", "RH", LEASE1); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ZERO_STRUCT(break_info); >+ >+ /* >+ * a open using the same lease key is still works, >+ * but reports SMB2_LEASE_FLAG_BREAK_IN_PROGRESS >+ */ >+ status = smb2_create(tree, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1b = io1.out.file.handle; >+ CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, SMB2_LEASE_FLAG_BREAK_IN_PROGRESS); >+ smb2_util_close(tree, h1b); >+ >+ CHECK_NO_BREAK(tctx); >+ >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ /* >+ * We are asked to break to "RH", but we are allowed to >+ * break to any of "RH", "R" or NONE. >+ */ >+ ack.in.lease.lease_state = SMB2_LEASE_NONE; >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE_BREAK_ACK(&ack, "", LEASE1); >+ >+ torture_assert(tctx, req2->cancel.can_cancel, >+ "req2 can_cancel"); >+ >+ status = smb2_create_recv(req2, tctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_VAL(io2.out.oplock_level, SMB2_OPLOCK_LEVEL_NONE); >+ >+ CHECK_NO_BREAK(tctx); >+done: >+ smb2_util_close(tree, h1a); >+ smb2_util_close(tree, h1b); >+ smb2_util_close(tree, h2); >+ smb2_util_unlink(tree, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -2780,6 +2887,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "breaking3", test_lease_breaking3); > torture_suite_add_1smb2_test(suite, "breaking4", test_lease_breaking4); > torture_suite_add_1smb2_test(suite, "breaking5", test_lease_breaking5); >+ torture_suite_add_1smb2_test(suite, "breaking6", test_lease_breaking6); > torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); >-- >1.9.1 > > >From 81d28774200bc9614b28cd1410b439b15b3fe877 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 14 Nov 2014 10:24:40 -0800 >Subject: [PATCH 36/47] s3: leases - torture test for timeout of responding to > lease break request. > >Passes against W2K12. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit f76c7c7404c1a67389b701bd1ab24d3b2938c212) >--- > source4/torture/smb2/lease.c | 130 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 130 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index 5e788e1..e1bc9b3 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -2866,6 +2866,135 @@ static bool test_lease_v2_complex1(struct torture_context *tctx, > return ret; > } > >+static bool test_lease_timeout(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io; >+ struct smb2_lease ls1; >+ struct smb2_lease ls2; >+ struct smb2_handle h, hnew, h1b; >+ NTSTATUS status; >+ const char *fname = "lease_timeout.dat"; >+ bool ret = true; >+ struct smb2_lease_break_ack ack = {}; >+ struct smb2_request *req2 = NULL; >+ struct smb2_write w; >+ uint32_t caps; >+ >+ caps = smb2cli_conn_server_capabilities(tree->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ smb2_util_unlink(tree, fname); >+ >+ /* Grab a RWH lease. */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RWH", true, LEASE1, 0); >+ h = io.out.file.handle; >+ >+ tree->session->transport->lease.handler = torture_lease_handler; >+ tree->session->transport->lease.private_data = tree; >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ >+ /* >+ * Just don't ack the lease break. >+ */ >+ ZERO_STRUCT(break_info); >+ break_info.lease_skip_ack = true; >+ >+ /* Break with a RWH request. */ >+ smb2_lease_create(&io, &ls2, false, fname, LEASE2, smb2_util_lease_state("RWH")); >+ req2 = smb2_create_send(tree, &io); >+ torture_assert(tctx, req2 != NULL, "smb2_create_send"); >+ torture_assert(tctx, req2->state == SMB2_REQUEST_RECV, "req2 pending"); >+ >+ CHECK_BREAK_INFO("RWH", "RH", LEASE1); >+ >+ /* Copy the break request. */ >+ ack.in.lease.lease_key = >+ break_info.lease_break.current_lease.lease_key; >+ ack.in.lease.lease_state = >+ break_info.lease_break.new_lease_state; >+ >+ /* Now wait for the timeout and get the reply. */ >+ status = smb2_create_recv(req2, tctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RH", true, LEASE2, 0); >+ hnew = io.out.file.handle; >+ >+ /* Ack the break after the timeout... */ >+ status = smb2_lease_break_ack(tree, &ack); >+ CHECK_STATUS(status, NT_STATUS_UNSUCCESSFUL); >+ >+ /* Get state of the original handle. */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE(&io, "", true, LEASE1, 0); >+ smb2_util_close(tree, io.out.file.handle); >+ >+ /* Write on the original handle and make sure it's still valid. */ >+ ZERO_STRUCT(break_info); >+ ZERO_STRUCT(w); >+ w.in.file.handle = h; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 4096); >+ memset(w.in.data.data, '1', w.in.data.length); >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ /* Causes new handle to break to NONE. */ >+ CHECK_BREAK_INFO("RH", "", LEASE2); >+ >+ /* Write on the new handle. */ >+ ZERO_STRUCT(break_info); >+ ZERO_STRUCT(w); >+ w.in.file.handle = hnew; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 1024); >+ memset(w.in.data.data, '2', w.in.data.length); >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ /* No break - original handle was already NONE. */ >+ CHECK_NO_BREAK(tctx); >+ smb2_util_close(tree, hnew); >+ >+ /* Upgrade to R on LEASE1. */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("R")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE(&io, "R", true, LEASE1, 0); >+ h1b = io.out.file.handle; >+ smb2_util_close(tree, h1b); >+ >+ /* Upgrade to RWH on LEASE1. */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE(&io, "RWH", true, LEASE1, 0); >+ h1b = io.out.file.handle; >+ smb2_util_close(tree, h1b); >+ >+ done: >+ smb2_util_close(tree, h); >+ smb2_util_close(tree, hnew); >+ smb2_util_close(tree, h1b); >+ >+ smb2_util_unlink(tree, fname); >+ >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ >+ > struct torture_suite *torture_smb2_lease_init(void) > { > struct torture_suite *suite = >@@ -2896,6 +3025,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "v2_epoch2", test_lease_v2_epoch2); > torture_suite_add_1smb2_test(suite, "v2_epoch3", test_lease_v2_epoch3); > torture_suite_add_1smb2_test(suite, "v2_complex1", test_lease_v2_complex1); >+ torture_suite_add_1smb2_test(suite, "timeout", test_lease_timeout); > > suite->description = talloc_strdup(suite, "SMB2-LEASE tests"); > >-- >1.9.1 > > >From 18a5e8e016d9a9adbdf08da463f2504552b21411 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Mon, 17 Nov 2014 14:17:34 -0800 >Subject: [PATCH 37/47] s4: smb2 : torture: Add new dynamic_share leases test. > >Depends on new share "dynamic_share" being set up containing an %R >in the path= statement. > >Shows we will break leases and fail to grant new ones >if we get a lease_key+client guid pair match on files >with different fileid's, as can happen on dynamic shares. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 62c6c79011d7e62423fa97d4cabd9de149af8311) >--- > selftest/target/Samba3.pm | 10 +++ > source4/torture/smb2/lease.c | 190 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 200 insertions(+) > >diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm >index ebe2c09..9a05464 100755 >--- a/selftest/target/Samba3.pm >+++ b/selftest/target/Samba3.pm >@@ -876,6 +876,12 @@ sub provision($$$$$$) > my $badnames_shrdir="$shrdir/badnames"; > push(@dirs,$badnames_shrdir); > >+ my $lease1_shrdir="$shrdir/SMB2_10"; >+ push(@dirs,$lease1_shrdir); >+ >+ my $lease2_shrdir="$shrdir/SMB3_00"; >+ push(@dirs,$lease2_shrdir); >+ > # this gets autocreated by winbindd > my $wbsockdir="$prefix_abs/winbindd"; > my $wbsockprivdir="$lockdir/winbindd_privileged"; >@@ -1220,6 +1226,10 @@ sub provision($$$$$$) > [badname-tmp] > path = $badnames_shrdir > guest ok = yes >+ >+[dynamic_share] >+ path = $shrdir/%R >+ guest ok = yes > "; > close(CONF); > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index e1bc9b3..db91548 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -27,6 +27,7 @@ > #include "torture/smb2/proto.h" > #include "torture/util.h" > #include "libcli/smb/smbXcli_base.h" >+#include "lib/param/param.h" > > #define CHECK_VAL(v, correct) do { \ > if ((v) != (correct)) { \ >@@ -2994,6 +2995,194 @@ static bool test_lease_timeout(struct torture_context *tctx, > return ret; > } > >+static bool test_lease_dynamic_share(struct torture_context *tctx, >+ struct smb2_tree *tree1a) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io; >+ struct smb2_lease ls1; >+ struct smb2_handle h, h1, h2; >+ struct smb2_write w; >+ NTSTATUS status; >+ const char *fname = "dynamic_path.dat"; >+ bool ret = true; >+ uint32_t caps; >+ struct smb2_tree *tree_2_1 = NULL; >+ struct smb2_tree *tree_3_0 = NULL; >+ struct smbcli_options options2_1; >+ struct smbcli_options options3_0; >+ const char *orig_share = NULL; >+ >+ if (!TARGET_IS_SAMBA3(tctx)) { >+ torture_skip(tctx, "dynamic shares are not supported"); >+ return true; >+ } >+ >+ options2_1 = tree1a->session->transport->options; >+ options3_0 = tree1a->session->transport->options; >+ >+ caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ /* >+ * Save off original share name and change it to dynamic_share. >+ * This must have been pre-created with a dynamic path containing >+ * %R. >+ */ >+ >+ orig_share = lpcfg_parm_string(tctx->lp_ctx, NULL, "torture", "share"); >+ orig_share = talloc_strdup(tctx->lp_ctx, orig_share); >+ if (orig_share == NULL) { >+ torture_result(tctx, TORTURE_FAIL, __location__ "no memory\n"); >+ ret = false; >+ goto done; >+ } >+ lpcfg_set_cmdline(tctx->lp_ctx, "torture:share", "dynamic_share"); >+ >+ /* Set max protocol to SMB2.1 */ >+ options2_1.max_protocol = PROTOCOL_SMB2_10; >+ /* create a new connection (same client_guid) */ >+ if (!torture_smb2_connection_ext(tctx, 0, &options2_1, &tree_2_1)) { >+ torture_warning(tctx, "couldn't reconnect max protocol 2.1, bailing\n"); >+ ret = false; >+ goto done; >+ } >+ >+ tree_2_1->session->transport->lease.handler = torture_lease_handler; >+ tree_2_1->session->transport->lease.private_data = tree_2_1; >+ tree_2_1->session->transport->oplock.handler = torture_oplock_handler; >+ tree_2_1->session->transport->oplock.private_data = tree_2_1; >+ >+ smb2_util_unlink(tree_2_1, fname); >+ >+ /* Set max protocol to SMB3.0 */ >+ options3_0.max_protocol = PROTOCOL_SMB3_00; >+ /* create a new connection (same client_guid) */ >+ if (!torture_smb2_connection_ext(tctx, 0, &options3_0, &tree_3_0)) { >+ torture_warning(tctx, "couldn't reconnect max protocol 3.0, bailing\n"); >+ ret = false; >+ goto done; >+ } >+ >+ tree_3_0->session->transport->lease.handler = torture_lease_handler; >+ tree_3_0->session->transport->lease.private_data = tree_3_0; >+ tree_3_0->session->transport->oplock.handler = torture_oplock_handler; >+ tree_3_0->session->transport->oplock.private_data = tree_3_0; >+ >+ smb2_util_unlink(tree_3_0, fname); >+ >+ ZERO_STRUCT(break_info); >+ >+ /* Get RWH lease over connection 2_1 */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree_2_1, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RWH", true, LEASE1, 0); >+ h = io.out.file.handle; >+ >+ /* Write some data into it. */ >+ w.in.file.handle = h; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 4096); >+ memset(w.in.data.data, '1', w.in.data.length); >+ status = smb2_write(tree_2_1, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ /* Open the same name over connection 3_0. */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree_3_0, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1 = io.out.file.handle; >+ CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ >+ /* h1 should have replied with NONE. */ >+ CHECK_LEASE(&io, "", true, LEASE1, 0); >+ >+ /* We should have broken h to NONE. */ >+ CHECK_BREAK_INFO("RWH", "", LEASE1); >+ >+ /* Try to upgrade to RWH over connection 2_1 */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree_2_1, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io.out.file.handle; >+ CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED); >+ CHECK_VAL(io.out.size, 4096); >+ CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE); >+ /* Should have been denied. */ >+ CHECK_LEASE(&io, "", true, LEASE1, 0); >+ smb2_util_close(tree_2_1, h2); >+ >+ /* Try to upgrade to RWH over connection 3_0 */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree_3_0, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io.out.file.handle; >+ CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED); >+ CHECK_VAL(io.out.size, 0); >+ CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE); >+ /* Should have been denied. */ >+ CHECK_LEASE(&io, "", true, LEASE1, 0); >+ smb2_util_close(tree_3_0, h2); >+ >+ /* Write some data into it. */ >+ w.in.file.handle = h1; >+ w.in.offset = 0; >+ w.in.data = data_blob_talloc(mem_ctx, NULL, 1024); >+ memset(w.in.data.data, '2', w.in.data.length); >+ status = smb2_write(tree_3_0, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ /* Close everything.. */ >+ smb2_util_close(tree_2_1, h); >+ smb2_util_close(tree_3_0, h1); >+ >+ /* And ensure we can get a lease ! */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree_2_1, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED); >+ CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RWH", true, LEASE1, 0); >+ h = io.out.file.handle; >+ /* And the file is the right size. */ >+ CHECK_VAL(io.out.size, 4096); \ >+ /* Close it. */ >+ smb2_util_close(tree_2_1, h); >+ >+ /* And ensure we can get a lease ! */ >+ smb2_lease_create(&io, &ls1, false, fname, LEASE1, smb2_util_lease_state("RWH")); >+ status = smb2_create(tree_3_0, mem_ctx, &io); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VAL(io.out.create_action, NTCREATEX_ACTION_EXISTED); >+ CHECK_VAL(io.out.file_attr, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io, "RWH", true, LEASE1, 0); >+ h = io.out.file.handle; >+ /* And the file is the right size. */ >+ CHECK_VAL(io.out.size, 1024); \ >+ /* Close it. */ >+ smb2_util_close(tree_3_0, h); >+ >+ done: >+ >+ smb2_util_close(tree_2_1, h); >+ smb2_util_close(tree_3_0, h1); >+ smb2_util_close(tree_3_0, h2); >+ >+ smb2_util_unlink(tree_2_1, fname); >+ smb2_util_unlink(tree_3_0, fname); >+ >+ /* Set sharename back. */ >+ lpcfg_set_cmdline(tctx->lp_ctx, "torture:share", orig_share); >+ >+ talloc_free(mem_ctx); >+ >+ return ret; >+} >+ > > struct torture_suite *torture_smb2_lease_init(void) > { >@@ -3025,6 +3214,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "v2_epoch2", test_lease_v2_epoch2); > torture_suite_add_1smb2_test(suite, "v2_epoch3", test_lease_v2_epoch3); > torture_suite_add_1smb2_test(suite, "v2_complex1", test_lease_v2_complex1); >+ torture_suite_add_1smb2_test(suite, "dynamic_share", test_lease_dynamic_share); > torture_suite_add_1smb2_test(suite, "timeout", test_lease_timeout); > > suite->description = talloc_strdup(suite, "SMB2-LEASE tests"); >-- >1.9.1 > > >From ce27b2e11f87cdaa34e09a2438cf43d759e964ca Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 21 Nov 2014 21:28:14 -0800 >Subject: [PATCH 38/47] s4: torture: leases - Add test for leases and blocking > locks. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> > >Autobuild-User(master): Stefan Metzmacher <metze@samba.org> >Autobuild-Date(master): Thu Nov 27 19:08:24 CET 2014 on sn-devel-104 > >(cherry picked from commit c6a5eab3690d2926d66024a35e3c3e818d7e4935) >--- > source4/torture/smb2/lease.c | 173 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 173 insertions(+) > >diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c >index db91548..c7b3592 100644 >--- a/source4/torture/smb2/lease.c >+++ b/source4/torture/smb2/lease.c >@@ -2596,6 +2596,178 @@ done: > return ret; > } > >+static bool test_lease_lock1(struct torture_context *tctx, >+ struct smb2_tree *tree1a, >+ struct smb2_tree *tree2) >+{ >+ TALLOC_CTX *mem_ctx = talloc_new(tctx); >+ struct smb2_create io1 = {}; >+ struct smb2_create io2 = {}; >+ struct smb2_create io3 = {}; >+ struct smb2_lease ls1 = {}; >+ struct smb2_lease ls2 = {}; >+ struct smb2_lease ls3 = {}; >+ struct smb2_handle h1 = {}; >+ struct smb2_handle h2 = {}; >+ struct smb2_handle h3 = {}; >+ struct smb2_lock lck; >+ struct smb2_lock_element el[1]; >+ const char *fname = "locktest.dat"; >+ bool ret = true; >+ NTSTATUS status; >+ uint32_t caps; >+ struct smbcli_options options1; >+ struct smb2_tree *tree1b = NULL; >+ >+ options1 = tree1a->session->transport->options; >+ >+ caps = smb2cli_conn_server_capabilities(tree1a->session->transport->conn); >+ if (!(caps & SMB2_CAP_LEASING)) { >+ torture_skip(tctx, "leases are not supported"); >+ } >+ >+ /* Set up handlers. */ >+ tree2->session->transport->lease.handler = torture_lease_handler; >+ tree2->session->transport->lease.private_data = tree2; >+ tree2->session->transport->oplock.handler = torture_oplock_handler; >+ tree2->session->transport->oplock.private_data = tree2; >+ >+ tree1a->session->transport->lease.handler = torture_lease_handler; >+ tree1a->session->transport->lease.private_data = tree1a; >+ tree1a->session->transport->oplock.handler = torture_oplock_handler; >+ tree1a->session->transport->oplock.private_data = tree1a; >+ >+ /* create a new connection (same client_guid) */ >+ if (!torture_smb2_connection_ext(tctx, 0, &options1, &tree1b)) { >+ torture_warning(tctx, "couldn't reconnect, bailing\n"); >+ ret = false; >+ goto done; >+ } >+ >+ tree1b->session->transport->lease.handler = torture_lease_handler; >+ tree1b->session->transport->lease.private_data = tree1b; >+ tree1b->session->transport->oplock.handler = torture_oplock_handler; >+ tree1b->session->transport->oplock.private_data = tree1b; >+ >+ smb2_util_unlink(tree1a, fname); >+ >+ ZERO_STRUCT(break_info); >+ ZERO_STRUCT(lck); >+ >+ /* Open a handle on tree1a. */ >+ smb2_lease_create_share(&io1, &ls1, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE1, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree1a, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h1 = io1.out.file.handle; >+ CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io1, "RWH", true, LEASE1, 0); >+ >+ /* Open a second handle on tree1b. */ >+ smb2_lease_create_share(&io2, &ls2, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE2, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree1b, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h2 = io2.out.file.handle; >+ CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io2, "RH", true, LEASE2, 0); >+ /* And LEASE1 got broken to RH. */ >+ CHECK_BREAK_INFO("RWH", "RH", LEASE1); >+ ZERO_STRUCT(break_info); >+ >+ /* Now open a lease on a different client guid. */ >+ smb2_lease_create_share(&io3, &ls3, false, fname, >+ smb2_util_share_access("RWD"), >+ LEASE3, >+ smb2_util_lease_state("RWH")); >+ status = smb2_create(tree2, mem_ctx, &io3); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ h3 = io3.out.file.handle; >+ CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE); >+ CHECK_LEASE(&io3, "RH", true, LEASE3, 0); >+ /* Doesn't break. */ >+ CHECK_NO_BREAK(tctx); >+ >+ lck.in.locks = el; >+ /* >+ * Try and get get an exclusive byte >+ * range lock on H1 (LEASE1). >+ */ >+ >+ lck.in.lock_count = 1; >+ lck.in.lock_sequence = 1; >+ lck.in.file.handle = h1; >+ el[0].offset = 0; >+ el[0].length = 1; >+ el[0].reserved = 0; >+ el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; >+ status = smb2_lock(tree1a, &lck); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ /* LEASE2 and LEASE3 should get broken to NONE. */ >+ torture_wait_for_lease_break(tctx); >+ torture_wait_for_lease_break(tctx); >+ torture_wait_for_lease_break(tctx); >+ torture_wait_for_lease_break(tctx); >+ >+ CHECK_VAL(break_info.failures, 0); \ >+ CHECK_VAL(break_info.count, 2); \ >+ >+ /* Get state of the H1 (LEASE1) */ >+ smb2_lease_create(&io1, &ls1, false, fname, LEASE1, smb2_util_lease_state("")); >+ status = smb2_create(tree1a, mem_ctx, &io1); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ /* Should still be RH. */ >+ CHECK_LEASE(&io1, "RH", true, LEASE1, 0); >+ smb2_util_close(tree1a, io1.out.file.handle); >+ >+ /* Get state of the H2 (LEASE2) */ >+ smb2_lease_create(&io2, &ls2, false, fname, LEASE2, smb2_util_lease_state("")); >+ status = smb2_create(tree1b, mem_ctx, &io2); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE(&io2, "", true, LEASE2, 0); >+ smb2_util_close(tree1b, io2.out.file.handle); >+ >+ /* Get state of the H3 (LEASE3) */ >+ smb2_lease_create(&io3, &ls3, false, fname, LEASE3, smb2_util_lease_state("")); >+ status = smb2_create(tree2, mem_ctx, &io3); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_LEASE(&io3, "", true, LEASE3, 0); >+ smb2_util_close(tree2, io3.out.file.handle); >+ >+ ZERO_STRUCT(break_info); >+ >+ /* >+ * Try and get get an exclusive byte >+ * range lock on H3 (LEASE3). >+ */ >+ lck.in.lock_count = 1; >+ lck.in.lock_sequence = 2; >+ lck.in.file.handle = h3; >+ el[0].offset = 100; >+ el[0].length = 1; >+ el[0].reserved = 0; >+ el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE; >+ status = smb2_lock(tree2, &lck); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ /* LEASE1 got broken to NONE. */ >+ CHECK_BREAK_INFO("RH", "", LEASE1); >+ ZERO_STRUCT(break_info); >+ >+done: >+ smb2_util_close(tree1a, h1); >+ smb2_util_close(tree1b, h2); >+ smb2_util_close(tree2, h3); >+ >+ smb2_util_unlink(tree1a, fname); >+ talloc_free(mem_ctx); >+ return ret; >+} >+ > static bool test_lease_complex1(struct torture_context *tctx, > struct smb2_tree *tree1a) > { >@@ -3206,6 +3378,7 @@ struct torture_suite *torture_smb2_lease_init(void) > torture_suite_add_1smb2_test(suite, "breaking4", test_lease_breaking4); > torture_suite_add_1smb2_test(suite, "breaking5", test_lease_breaking5); > torture_suite_add_1smb2_test(suite, "breaking6", test_lease_breaking6); >+ torture_suite_add_2smb2_test(suite, "lock1", test_lease_lock1); > torture_suite_add_1smb2_test(suite, "complex1", test_lease_complex1); > torture_suite_add_1smb2_test(suite, "v2_request_parent", > test_lease_v2_request_parent); >-- >1.9.1 > > >From c6545a39727d713ba0ad678625c6a19861a33187 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Mon, 29 Sep 2014 15:06:37 +0000 >Subject: [PATCH 39/47] profiling: Make "struct profile_header" static > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 7c1f6c7f61f27ec8e115cdce1e2ac15addd8fb84) >--- > source3/include/smbprofile.h | 7 ------- > source3/profile/profile.c | 8 +++++++- > 2 files changed, 7 insertions(+), 8 deletions(-) > >diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h >index 8ecbc30..9ffcfc4 100644 >--- a/source3/include/smbprofile.h >+++ b/source3/include/smbprofile.h >@@ -876,13 +876,6 @@ struct profile_stats { > unsigned writecache_allocated_write_caches; > }; > >-struct profile_header { >- int prof_shm_magic; >- int prof_shm_version; >- struct profile_stats stats; >-}; >- >-extern struct profile_header *profile_h; > extern struct profile_stats *profile_p; > extern bool do_profile_flag; > extern bool do_profile_times; >diff --git a/source3/profile/profile.c b/source3/profile/profile.c >index 5f9433f..e0e4684 100644 >--- a/source3/profile/profile.c >+++ b/source3/profile/profile.c >@@ -34,7 +34,13 @@ static int shm_id; > static bool read_only; > #endif > >-struct profile_header *profile_h; >+struct profile_header { >+ int prof_shm_magic; >+ int prof_shm_version; >+ struct profile_stats stats; >+}; >+ >+static struct profile_header *profile_h; > struct profile_stats *profile_p; > > bool do_profile_flag = False; >-- >1.9.1 > > >From 59e8e40d8f75043ddb93c04fdb154cbd0ac5fee1 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 30 Sep 2014 13:06:02 +0000 >Subject: [PATCH 40/47] profiling: Fix a typo > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit d523e0b7ed67d1697a1b8ab5f58902afd2a496b3) >--- > source3/include/smbprofile.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h >index 9ffcfc4..fd17b7a 100644 >--- a/source3/include/smbprofile.h >+++ b/source3/include/smbprofile.h >@@ -835,7 +835,7 @@ enum profile_stats_values > #define smb2_break_count __profile_stats_value(PR_VALUE_SMB2_BREAK, count) > #define smb2_break_time __profile_stats_value(PR_VALUE_SMB2_BREAK, time) > >- /* This mist remain the last value. */ >+ /* This must remain the last value. */ > PR_VALUE_MAX > }; /* enum profile_stats_values */ > >-- >1.9.1 > > >From ccc0f2e9354a810a6f668196b25163f63cf28437 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Thu, 2 Oct 2014 12:52:05 +0000 >Subject: [PATCH 41/47] profiling: Move some #defines to profile.c > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 0e1b60e8c3325a1e5ea77f420326b254d5404389) >--- > source3/include/smbprofile.h | 4 ---- > source3/profile/profile.c | 4 ++++ > 2 files changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h >index fd17b7a..3040aa0 100644 >--- a/source3/include/smbprofile.h >+++ b/source3/include/smbprofile.h >@@ -24,10 +24,6 @@ > /* this file defines the profile structure in the profile shared > memory area */ > >-#define PROF_SHMEM_KEY ((key_t)0x07021999) >-#define PROF_SHM_MAGIC 0x6349985 >-#define PROF_SHM_VERSION 13 >- > /* time values in the following structure are in microseconds */ > > #define __profile_stats_value(which, domain) domain[which] >diff --git a/source3/profile/profile.c b/source3/profile/profile.c >index e0e4684..9ef2c69 100644 >--- a/source3/profile/profile.c >+++ b/source3/profile/profile.c >@@ -25,6 +25,10 @@ > #include "messages.h" > #include "smbprofile.h" > >+#define PROF_SHMEM_KEY ((key_t)0x07021999) >+#define PROF_SHM_MAGIC 0x6349985 >+#define PROF_SHM_VERSION 13 >+ > #ifdef WITH_PROFILE > #define IPC_PERMS ((S_IRUSR | S_IWUSR) | S_IRGRP | S_IROTH) > #endif /* WITH_PROFILE */ >-- >1.9.1 > > >From 1f3bc5f5c93bca86d76672675a0bc00bcfc36332 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Thu, 2 Oct 2014 13:05:07 +0000 >Subject: [PATCH 42/47] profiling: Fix a typo > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit a33b445a7d7567b27f5247cb6060edbbeecf4d52) >--- > source3/include/smbprofile.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h >index 3040aa0..97e7c70 100644 >--- a/source3/include/smbprofile.h >+++ b/source3/include/smbprofile.h >@@ -880,7 +880,7 @@ extern bool do_profile_times; > > /* these are helper macros - do not call them directly in the code > * use the DO_PROFILE_* START_PROFILE and END_PROFILE ones >- * below which test for the profile flage first >+ * below which test for the profile flags first > */ > #define INC_PROFILE_COUNT(x) profile_p->x++ > #define DEC_PROFILE_COUNT(x) profile_p->x-- >-- >1.9.1 > > >From 1c3337f4ab2742daa0506f985e8c2cd0feb581a0 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 30 Sep 2014 15:08:20 +0000 >Subject: [PATCH 43/47] profiling: Only compile utils/status_profile.c if > profiling is enabled > >This conditional compile avoids some #ifdef WITH_PROFILE, which makes the code >more readable > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 17c7f454813be526876ac750ceb6fd1422577495) >--- > source3/utils/status_profile.c | 21 --------------------- > source3/utils/status_profile_dummy.c | 33 +++++++++++++++++++++++++++++++++ > source3/wscript_build | 11 ++++++++--- > 3 files changed, 41 insertions(+), 24 deletions(-) > create mode 100644 source3/utils/status_profile_dummy.c > >diff --git a/source3/utils/status_profile.c b/source3/utils/status_profile.c >index 0923bae..153fba6 100644 >--- a/source3/utils/status_profile.c >+++ b/source3/utils/status_profile.c >@@ -24,7 +24,6 @@ > bool status_profile_dump(bool be_verbose); > bool status_profile_rates(bool be_verbose); > >-#ifdef WITH_PROFILE > static void profile_separator(const char * title) > { > char line[79 + 1]; >@@ -39,14 +38,12 @@ static void profile_separator(const char * title) > line[sizeof(line) - 1] = '\0'; > d_printf("%s\n", line); > } >-#endif > > /******************************************************************* > dump the elements of the profile structure > ******************************************************************/ > bool status_profile_dump(bool verbose) > { >-#ifdef WITH_PROFILE > if (!profile_setup(NULL, True)) { > fprintf(stderr,"Failed to initialise profile memory\n"); > return False; >@@ -437,16 +434,9 @@ bool status_profile_dump(bool verbose) > d_printf("smb2_break_count: %u\n", profile_p->smb2_break_count); > d_printf("smb2_break_time: %u\n", profile_p->smb2_break_time); > >-#else /* WITH_PROFILE */ >- >- fprintf(stderr, "Profile data unavailable\n"); >-#endif /* WITH_PROFILE */ >- > return True; > } > >-#ifdef WITH_PROFILE >- > /* Convert microseconds to milliseconds. */ > #define usec_to_msec(s) ((s) / 1000) > /* Convert microseconds to seconds. */ >@@ -566,14 +556,3 @@ bool status_profile_rates(bool verbose) > > return True; > } >- >-#else /* WITH_PROFILE */ >- >-bool status_profile_rates(bool verbose) >-{ >- fprintf(stderr, "Profile data unavailable\n"); >- return False; >-} >- >-#endif /* WITH_PROFILE */ >- >diff --git a/source3/utils/status_profile_dummy.c b/source3/utils/status_profile_dummy.c >new file mode 100644 >index 0000000..c58f696 >--- /dev/null >+++ b/source3/utils/status_profile_dummy.c >@@ -0,0 +1,33 @@ >+/* >+ * Unix SMB/CIFS implementation. >+ * Samba internal messaging functions >+ * Copyright (C) 2013 by Volker Lendecke >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 3 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program. If not, see <http://www.gnu.org/licenses/>. >+ */ >+ >+#include "includes.h" >+#include "smbprofile.h" >+ >+bool status_profile_dump(bool be_verbose) >+{ >+ fprintf(stderr, "Profile data unavailable\n"); >+ return true; >+} >+ >+bool status_profile_rates(bool be_verbose) >+{ >+ fprintf(stderr, "Profile data unavailable\n"); >+ return true; >+} >diff --git a/source3/wscript_build b/source3/wscript_build >index 7394a57..d3979e8 100755 >--- a/source3/wscript_build >+++ b/source3/wscript_build >@@ -1164,10 +1164,15 @@ bld.SAMBA3_BINARY('smbta-util', > secrets3 > param''') > >+smbstatus_source = 'utils/status.c smbd/notify_internal.c' >+ >+if bld.CONFIG_GET("WITH_PROFILE"): >+ smbstatus_source += ' utils/status_profile.c' >+else: >+ smbstatus_source += ' utils/status_profile_dummy.c' >+ > bld.SAMBA3_BINARY('smbstatus', >- source='''utils/status.c >- utils/status_profile.c >- smbd/notify_internal.c''', >+ source=smbstatus_source, > deps=''' > talloc > param >-- >1.9.1 > > >From ad6bffc4d3a3ead5cf02dc14ba0ad56628f8f02d Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 30 Sep 2014 15:08:20 +0000 >Subject: [PATCH 44/47] profiling: Only compile profile/profile.c if profiling > is enabled > >This conditional compile avoids some #ifdef WITH_PROFILE, which makes the code >more readable > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit c7c300f9710f1f207b9fa0274648ba2dc11c1ffd) >--- > source3/profile/profile.c | 17 +---------------- > source3/profile/profile_dummy.c | 31 +++++++++++++++++++++++++++++++ > source3/wscript_build | 11 ++++++++--- > 3 files changed, 40 insertions(+), 19 deletions(-) > create mode 100644 source3/profile/profile_dummy.c > >diff --git a/source3/profile/profile.c b/source3/profile/profile.c >index 9ef2c69..9367ff4 100644 >--- a/source3/profile/profile.c >+++ b/source3/profile/profile.c >@@ -29,14 +29,10 @@ > #define PROF_SHM_MAGIC 0x6349985 > #define PROF_SHM_VERSION 13 > >-#ifdef WITH_PROFILE > #define IPC_PERMS ((S_IRUSR | S_IWUSR) | S_IRGRP | S_IROTH) >-#endif /* WITH_PROFILE */ > >-#ifdef WITH_PROFILE > static int shm_id; > static bool read_only; >-#endif > > struct profile_header { > int prof_shm_magic; >@@ -55,7 +51,6 @@ Set a profiling level. > ****************************************************************************/ > void set_profile_level(int level, struct server_id src) > { >-#ifdef WITH_PROFILE > switch (level) { > case 0: /* turn off profiling */ > do_profile_flag = False; >@@ -81,13 +76,8 @@ void set_profile_level(int level, struct server_id src) > (int)procid_to_pid(&src))); > break; > } >-#else /* WITH_PROFILE */ >- DEBUG(1,("INFO: Profiling support unavailable in this build.\n")); >-#endif /* WITH_PROFILE */ > } > >-#ifdef WITH_PROFILE >- > /**************************************************************************** > receive a set profile level message > ****************************************************************************/ >@@ -119,11 +109,8 @@ static void reqprofile_message(struct messaging_context *msg_ctx, > { > int level; > >-#ifdef WITH_PROFILE > level = 1 + (do_profile_flag?2:0) + (do_profile_times?4:0); >-#else >- level = 0; >-#endif >+ > DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n", > (unsigned int)procid_to_pid(&src))); > messaging_send_buf(msg_ctx, src, MSG_PROFILELEVEL, >@@ -413,5 +400,3 @@ bool profile_setup(struct messaging_context *msg_ctx, bool rdonly) > SMB_ASSERT(val < PR_VALUE_MAX); > return valnames[val]; > } >- >-#endif /* WITH_PROFILE */ >diff --git a/source3/profile/profile_dummy.c b/source3/profile/profile_dummy.c >new file mode 100644 >index 0000000..1f820ec >--- /dev/null >+++ b/source3/profile/profile_dummy.c >@@ -0,0 +1,31 @@ >+/* >+ * Unix SMB/CIFS implementation. >+ * profile.c implementation if profiles are not enabled >+ * Copyright (C) Volker Lendecke 2014 >+ * >+ * This program is free software; you can redistribute it and/or modify >+ * it under the terms of the GNU General Public License as published by >+ * the Free Software Foundation; either version 3 of the License, or >+ * (at your option) any later version. >+ * >+ * This program is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ * GNU General Public License for more details. >+ * >+ * You should have received a copy of the GNU General Public License >+ * along with this program. If not, see <http://www.gnu.org/licenses/>. >+ */ >+ >+#include "includes.h" >+#include "smbprofile.h" >+ >+bool profile_setup(struct messaging_context *msg_ctx, bool rdonly) >+{ >+ return true; >+} >+ >+void set_profile_level(int level, struct server_id src) >+{ >+ DEBUG(1,("INFO: Profiling support unavailable in this build.\n")); >+} >diff --git a/source3/wscript_build b/source3/wscript_build >index d3979e8..54ba3a7 100755 >--- a/source3/wscript_build >+++ b/source3/wscript_build >@@ -638,9 +638,14 @@ bld.SAMBA3_SUBSYSTEM('LOCKING', > NDR_OPEN_FILES > FNAME_UTIL''') > >-bld.SAMBA3_SUBSYSTEM('PROFILE', >- source='profile/profile.c', >- deps='samba-util') >+if bld.CONFIG_GET("WITH_PROFILE"): >+ bld.SAMBA3_SUBSYSTEM('PROFILE', >+ source='profile/profile.c', >+ deps='samba-util') >+else: >+ bld.SAMBA3_SUBSYSTEM('PROFILE', >+ source='profile/profile_dummy.c', >+ deps='') > > bld.SAMBA3_SUBSYSTEM('PRINTBASE', > source='''printing/notify.c printing/printing_db.c''', >-- >1.9.1 > > >From 004037fc7e9da4006ab9b23a1f1c4d69efbe461a Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Thu, 2 Oct 2014 13:36:22 +0000 >Subject: [PATCH 45/47] profiling: Remove some #ifdefs > >The DO_PROFILE_INC thingies already #define to nothing without >WITH_PROFILE, and any sane compiler will just not compile the if-condition >if there is no body to be executed. > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 5254a7e1e5ab216a679bfbf3584bb8a16f502a2b) >--- > source3/smbd/fileio.c | 6 ------ > source3/smbd/server.c | 2 -- > 2 files changed, 8 deletions(-) > >diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c >index b0da7a2..91b3102 100644 >--- a/source3/smbd/fileio.c >+++ b/source3/smbd/fileio.c >@@ -345,12 +345,10 @@ ssize_t write_file(struct smb_request *req, > > mark_file_modified(fsp); > >-#ifdef WITH_PROFILE > DO_PROFILE_INC(writecache_total_writes); > if (!fsp->oplock_type) { > DO_PROFILE_INC(writecache_non_oplock_writes); > } >-#endif > > /* > * If this file is level II oplocked then we need >@@ -826,13 +824,11 @@ n = %u, wcp->offset=%.0f, wcp->data_size=%u\n", > */ > > if (n) { >-#ifdef WITH_PROFILE > if (wcp->data_size) { > DO_PROFILE_INC(writecache_abutted_writes); > } else { > DO_PROFILE_INC(writecache_init_writes); > } >-#endif > > if ((wcp->data_size == 0) > && (pos > wcp->file_size) >@@ -997,11 +993,9 @@ ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason) > DEBUG(9,("flushing write cache: fd = %d, off=%.0f, size=%u\n", > fsp->fh->fd, (double)wcp->offset, (unsigned int)data_size)); > >-#ifdef WITH_PROFILE > if(data_size == wcp->alloc_size) { > DO_PROFILE_INC(writecache_num_perfect_writes); > } >-#endif > > ret = real_write_file(NULL, fsp, wcp->data, wcp->offset, data_size); > >diff --git a/source3/smbd/server.c b/source3/smbd/server.c >index 658f268..8b9a1c1 100644 >--- a/source3/smbd/server.c >+++ b/source3/smbd/server.c >@@ -1304,7 +1304,6 @@ extern void build_options(bool screen); > > init_structs(); > >-#ifdef WITH_PROFILE > if (!profile_setup(msg_ctx, False)) { > DEBUG(0,("ERROR: failed to setup profiling\n")); > return -1; >@@ -1317,7 +1316,6 @@ extern void build_options(bool screen); > src.pid = getpid(); > set_profile_level(pl, src); > } >-#endif > > if (!is_daemon && !is_a_socket(0)) { > if (!interactive) { >-- >1.9.1 > > >From a7295493f6ce0756b0a1dce33b681d1b8b5515fd Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Thu, 2 Oct 2014 13:40:35 +0000 >Subject: [PATCH 46/47] profiling: Remove a big DEBUG statement > >I would like to have the freedom to play with the profiling implementation. >This is kindof in the way. > >This code is from pre-SVN days: > >> commit 7914e9351abb5271ebb4990c3b1fe495d15a4eda >> Author: Jeremy Allison <jra@samba.org> >> AuthorDate: Thu Oct 5 18:50:18 2000 +0000 >> Commit: Jeremy Allison <jra@samba.org> >> CommitDate: Thu Oct 5 18:50:18 2000 +0000 >> >> Herb's fixes for profiling & compiler warnings. >> Jeremy. > >Herb, please speak up quickly if you still need this :-) > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit f74ac712aea8d354b70966ffd3f617c65a17d8d0) >--- > source3/smbd/fileio.c | 25 ------------------------- > 1 file changed, 25 deletions(-) > >diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c >index 91b3102..37c3f66 100644 >--- a/source3/smbd/fileio.c >+++ b/source3/smbd/fileio.c >@@ -362,31 +362,6 @@ ssize_t write_file(struct smb_request *req, > contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE); > contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE); > >-#ifdef WITH_PROFILE >- if (profile_p && profile_p->writecache_total_writes % 500 == 0) { >- DEBUG(3,("WRITECACHE: initwrites=%u abutted=%u total=%u \ >-nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", >- profile_p->writecache_init_writes, >- profile_p->writecache_abutted_writes, >- profile_p->writecache_total_writes, >- profile_p->writecache_non_oplock_writes, >- profile_p->writecache_allocated_write_caches, >- profile_p->writecache_num_write_caches, >- profile_p->writecache_direct_writes, >- profile_p->writecache_num_perfect_writes, >- profile_p->writecache_read_hits )); >- >- DEBUG(3,("WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d\n", >- profile_p->writecache_flushed_writes[SAMBA_SEEK_FLUSH], >- profile_p->writecache_flushed_writes[SAMBA_READ_FLUSH], >- profile_p->writecache_flushed_writes[SAMBA_WRITE_FLUSH], >- profile_p->writecache_flushed_writes[SAMBA_READRAW_FLUSH], >- profile_p->writecache_flushed_writes[SAMBA_OPLOCK_RELEASE_FLUSH], >- profile_p->writecache_flushed_writes[SAMBA_CLOSE_FLUSH], >- profile_p->writecache_flushed_writes[SAMBA_SYNC_FLUSH] )); >- } >-#endif >- > if (wcp && req->unread_bytes) { > /* If we're using receivefile don't > * deal with a write cache. >-- >1.9.1 > > >From 23de486e5d2e178cd6ecadbf18d6fb64960b42c4 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Thu, 2 Oct 2014 13:45:01 +0000 >Subject: [PATCH 47/47] profiling: Make WITH_PROFILE span more in smbprofile.h > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Fri Oct 3 22:17:46 CEST 2014 on sn-devel-104 > >(cherry picked from commit 5496270d0f615aa39de0a083ec74fb40a988f64b) >--- > source3/include/smbprofile.h | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > >diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h >index 97e7c70..a37ac4f 100644 >--- a/source3/include/smbprofile.h >+++ b/source3/include/smbprofile.h >@@ -21,6 +21,8 @@ > > */ > >+#ifdef WITH_PROFILE >+ > /* this file defines the profile structure in the profile shared > memory area */ > >@@ -876,8 +878,6 @@ extern struct profile_stats *profile_p; > extern bool do_profile_flag; > extern bool do_profile_times; > >-#ifdef WITH_PROFILE >- > /* these are helper macros - do not call them directly in the code > * use the DO_PROFILE_* START_PROFILE and END_PROFILE ones > * below which test for the profile flags first >@@ -964,6 +964,7 @@ static inline uint64_t profile_timestamp(void) > #define START_PROFILE_BYTES(x,n) > #define END_PROFILE_STAMP(x, _stamp) > #define END_PROFILE(x) >+ > #endif /* WITH_PROFILE */ > > /* The following definitions come from profile/profile.c */ >-- >1.9.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
jra
:
review+
Actions:
View
Attachments on
bug 10911
:
10394
|
10396
|
10397
|
10399
|
10400
|
10401
|
10406
|
10407
|
10411
|
10412
|
10415
|
10416
|
10417
|
10418
|
10421
|
10478
| 10479 |
10481
|
10484
|
10486
|
10488
|
10492
|
10493
|
10507
|
10546