From: Sachin Prabhu Date: Fri, 2 Feb 2018 08:39:39 +0000 (+0530) Subject: Clean up tests for lease breaks over multichannel X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=906427ff3a64cfdde2ec994df26a57d31e336d0a;p=obnox%2Fsamba%2Fsamba-obnox.git Clean up tests for lease breaks over multichannel Signed-off-by: Sachin Prabhu --- diff --git a/source4/torture/smb2/multichannel.c b/source4/torture/smb2/multichannel.c index b4d5929fdff..679716d0b7f 100644 --- a/source4/torture/smb2/multichannel.c +++ b/source4/torture/smb2/multichannel.c @@ -815,6 +815,7 @@ done: static const uint64_t LEASE1F1 = 0xBADC0FFEE0DDF00Dull; static const uint64_t LEASE1F2 = 0xBADC0FFEE0DDD00Dull; +static const uint64_t LEASE1F3 = 0xDADC0FFEE0DDD00Dull; static const uint64_t LEASE2F1 = 0xDEADBEEFFEEDBEADull; static const uint64_t LEASE2F2 = 0xDAD0FFEDD00DF00Dull; static const uint64_t LEASE2F3 = 0xBAD0FFEDD00DF00Dull; @@ -894,6 +895,9 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, transport1->lease.private_data = tree1; torture_comment(tctx, "transport1 [%p]\n", transport1); + local_port = torture_get_local_port_from_transport(transport1); + torture_comment(tctx, "transport1 uses tcp port: %d\n", local_port); + status = torture_smb2_testdir(tree1, BASEDIR, &_h); CHECK_STATUS(status, NT_STATUS_OK); smb2_util_close(tree1, _h); @@ -902,6 +906,18 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, smb2_util_unlink(tree1, fname3); CHECK_VAL(lease_break_info.count, 0); + /* + * Test 1: + * open file1 in session 2A + * open file2 in session 2B + * open file3 in session 2B + * open file1 in session 1 + * lease break sent to 2A + * open file2 in session 2 + * lease break sent to 2B + */ + torture_comment(tctx, "Test 1 start \n"); + smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1, smb2_util_lease_state("RHW")); io1.in.durable_open = false; @@ -946,12 +962,16 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, transport2A = tree2A->session->transport; session2A = tree2A->session; + transport2A->lease.handler = torture_lease_handler; transport2A->lease.private_data = tree2A; torture_comment(tctx, "transport2A [%p]\n", transport2A); torture_comment(tctx, "established transport 2A\n"); + local_port = torture_get_local_port_from_transport(transport2A); + torture_comment(tctx, "transport2A uses tcp port: %d\n", local_port); + status = smb2_connect(tctx, host, lpcfg_smb_ports(tctx->lp_ctx), @@ -986,6 +1006,9 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, torture_comment(tctx, "established transport 2B\n"); + local_port = torture_get_local_port_from_transport(transport2B); + torture_comment(tctx, "transport2B uses tcp port: %d\n", local_port); + status = smb2_session_setup_spnego(session2B, popt_get_cmdline_credentials(), 0 /* previous_session_id */); @@ -1024,6 +1047,19 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, CHECK_VAL(io2.out.durable_open, false); CHECK_VAL(lease_break_info.count, 0); + torture_comment(tctx, "client2 opens fname3 via session 2B\n"); + /* 2b opens file3 */ + smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3, + smb2_util_lease_state("RHW")); + status = smb2_create(tree2B, mem_ctx, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + h_client2_file3 = io3.out.file.handle; + CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io3, "RHW", true, LEASE2F3, 0); + CHECK_VAL(io3.out.durable_open_v2, false); + CHECK_VAL(io3.out.timeout, io3.in.timeout); + CHECK_VAL(io3.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 0); /* * 1 opens file1 @@ -1084,6 +1120,18 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, smb2_util_unlink(tree1, fname3); CHECK_VAL(lease_break_info.count, 0); + /* + * Test 2: + * open file1 in session 2A + * open file2 in session 2B + * open file3 in session 2C + * open file1 in session 1 + * lease break sent to 2A + * open file2 in session 2 + * lease break sent to 2B + */ + torture_comment(tctx, "Test 2 start \n"); + /* now add a third channel and repeat the test */ status = smb2_connect(tctx, host, @@ -1136,7 +1184,6 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, smb2_keepalive(transport2C); local_port = torture_get_local_port_from_transport(transport2C); - torture_comment(tctx, "transport2C uses tcp port: %d\n", local_port); torture_comment(tctx, "client2 opens fname1 via session 2A\n"); @@ -1150,7 +1197,7 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, h_client2_file1 = io1.out.file.handle; CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0); - CHECK_VAL(io1.out.durable_open_v2, false); //true); + CHECK_VAL(io1.out.durable_open_v2, false); CHECK_VAL(io1.out.timeout, io1.in.timeout); CHECK_VAL(io1.out.durable_open, false); CHECK_VAL(lease_break_info.count, 0); @@ -1166,67 +1213,29 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, h_client2_file2 = io2.out.file.handle; CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE); CHECK_LEASE(&io2, "RHW", true, LEASE2F2, 0); - CHECK_VAL(io2.out.durable_open_v2, false); //true); + CHECK_VAL(io2.out.durable_open_v2, false); CHECK_VAL(io2.out.timeout, io2.in.timeout); CHECK_VAL(io2.out.durable_open, false); CHECK_VAL(lease_break_info.count, 0); + torture_comment(tctx, "client2 opens fname3 via session 2C\n"); - block_ok = torture_block_tcp_transport(tctx, transport2A); - block_ok = torture_block_tcp_transport(tctx, transport2B); - block_ok = torture_block_tcp_transport(tctx, transport2C); - smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1, + /* 2c opens file3 */ + smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3, smb2_util_lease_state("RHW")); - { - struct smb2_request *req; - // uint32_t pkts2A = 0; - // uint32_t pkts2B = 0; - // uint32_t pkts2C = 0; - uint32_t pkts2Ainit = 0; - uint32_t pkts2Binit = 0; - uint32_t pkts2Cinit = 0; - req = smb2_create_send(tree1, &io1); - - while (req->cancel.can_cancel == false) { - tevent_loop_once(tctx->ev); - } - - smb_msleep(1000); - torture_list_tcp_transport(tctx, transport2A, &pkts2Ainit); - torture_list_tcp_transport(tctx, transport2B, &pkts2Binit); - torture_list_tcp_transport(tctx, transport2C, &pkts2Cinit); -#if 0 - for (int i = 0; i < 10; i++) { - - smb_msleep(1000); - torture_list_tcp_transport(tctx, transport2A, &pkts2A); - torture_list_tcp_transport(tctx, transport2B, &pkts2B); - torture_list_tcp_transport(tctx, transport2C, &pkts2C); - } -#endif - if (pkts2Ainit == 0) { - unblock_ok = torture_unblock_tcp_transport(tctx, transport2A); - } - - if (pkts2Binit == 0) { - unblock_ok = torture_unblock_tcp_transport(tctx, transport2B); - } - - if (pkts2Cinit == 0) { - unblock_ok = torture_unblock_tcp_transport(tctx, transport2C); - } - - smb_msleep(40000); - } - unblock_ok = torture_unblock_tcp_transport(tctx, transport2C); - unblock_ok = torture_unblock_tcp_transport(tctx, transport2A); - unblock_ok = torture_unblock_tcp_transport(tctx, transport2B); - torture_unblock_cleanup(tctx); - exit(0); + status = smb2_create(tree2C, mem_ctx, &io3); + CHECK_STATUS(status, NT_STATUS_OK); + h_client2_file3 = io3.out.file.handle; + CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io3, "RHW", true, LEASE2F3, 0); + CHECK_VAL(io3.out.durable_open_v2, false); + CHECK_VAL(io3.out.timeout, io2.in.timeout); + CHECK_VAL(io3.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 0); /* * 1 opens file1 - * batchoplock break? + * lease break? */ torture_comment(tctx, "client1 opens fname1 via session 1\n"); @@ -1247,15 +1256,6 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, torture_reset_lease_break_info(tctx, &lease_break_info); - - for (int i = 0; i < 25; i++) { - torture_list_tcp_transport(tctx, transport2A, NULL); - torture_list_tcp_transport(tctx, transport2B, NULL); - torture_list_tcp_transport(tctx, transport2C, NULL); - smb_msleep(1000); - } - torture_assert(tctx, block_ok, "we could not block tcp transport"); - /* * 1 opens file2 * lease break? @@ -1269,73 +1269,150 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, CHECK_STATUS(status, NT_STATUS_OK); h_client1_file2 = io2.out.file.handle; CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); - CHECK_LEASE(&io2, "RHW", true, LEASE1F2, 0); -// CHECK_BREAK_INFO("RHW", "RH", LEASE2F2); + CHECK_LEASE(&io2, "RH", true, LEASE1F2, 0); + CHECK_BREAK_INFO("RHW", "RH", LEASE2F2); CHECK_VAL(io2.out.durable_open_v2, false); CHECK_VAL(io2.out.timeout, 0); CHECK_VAL(io2.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 1); + CHECK_PTR(lease_break_info.lease_transport, transport2A); + + /* cleanup everything */ + torture_reset_lease_break_info(tctx, &lease_break_info); + + smb2_util_close(tree1, h_client1_file1); + smb2_util_close(tree1, h_client1_file2); + smb2_util_close(tree1, h_client1_file3); + smb2_util_close(tree2A, h_client2_file1); + smb2_util_close(tree2A, h_client2_file2); + smb2_util_close(tree2A, h_client2_file3); + + smb2_util_unlink(tree1, fname1); + smb2_util_unlink(tree1, fname2); + smb2_util_unlink(tree1, fname3); + CHECK_VAL(lease_break_info.count, 0); /* - * FIXME LEASES! Important: when filtered, Windows will really let the open succeed - * and *NOT* send a new oplock break over the remaining channels, thus - * the break info count stays at one. + * Test 3: + * open file1 in session 2A + * open file2 in session 2B + * open file3 in session 2C + * block 2B 2C + * open file2 in session 1 + * lease break reaches through session 2A + * server allows session 1 to open file1 + * unblock 2B 2C, send keep alive + * open file1 in session 1 + * lease break sent to 2A */ + torture_comment(tctx, "Test 3 start \n"); - CHECK_VAL(lease_break_info.count, 1); + /* 2a opens file1 */ - torture_reset_lease_break_info(tctx, &lease_break_info); + torture_comment(tctx, "client2 opens fname1 via session 2A\n"); - blob = data_blob_string_const("Here I am"); + smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1, + smb2_util_lease_state("RHW")); + status = smb2_create(tree2A, mem_ctx, &io1); + CHECK_STATUS(status, NT_STATUS_OK); + h_client2_file1 = io1.out.file.handle; + CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0); + CHECK_VAL(io1.out.durable_open_v2, false); //true); + CHECK_VAL(io1.out.timeout, io1.in.timeout); + CHECK_VAL(io1.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 0); - torture_comment(tctx, "Trying write to file2 on tree2B\n"); - status = smb2_util_write(tree2B, - h_client2_file2, - blob.data, - 0, - blob.length); - torture_assert_ntstatus_ok(tctx, status, - "failed to write file2 via channel 2B"); + torture_comment(tctx, "client2 opens fname2 via session 2B\n"); - smb2_util_close(tree1, h_client1_file2); + /* 2b opens file2 */ + smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2, + smb2_util_lease_state("RHW")); + status = smb2_create(tree2B, mem_ctx, &io2); + CHECK_STATUS(status, NT_STATUS_OK); + h_client2_file2 = io2.out.file.handle; + CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io2, "RHW", true, LEASE2F2, 0); + CHECK_VAL(io2.out.durable_open_v2, false); //true); + CHECK_VAL(io2.out.timeout, io2.in.timeout); + CHECK_VAL(io2.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 0); + + + torture_comment(tctx, "Blocking 2B and 2C\n"); + /* Block 2A, 2B and 2C */ + //block_ok = torture_block_tcp_transport(tctx, transport2A); + block_ok = torture_block_tcp_transport(tctx, transport2B); + block_ok |= torture_block_tcp_transport(tctx, transport2C); + torture_assert(tctx, block_ok, "we could not block tcp transport"); + /* + * 1 opens file2 + * batchoplock break? + */ + + torture_comment(tctx, "Client opens fname2 with session 1 with 2B and 2C blocked\n"); smb2_lease_create(&io2, &ls2, false, fname2, LEASE1F2, smb2_util_lease_state("RHW")); status = smb2_create(tree1, mem_ctx, &io2); CHECK_STATUS(status, NT_STATUS_OK); h_client1_file2 = io2.out.file.handle; - io2.out.alloc_size = 0; - io2.out.size = 0; CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); CHECK_LEASE(&io2, "RH", true, LEASE1F2, 0); CHECK_BREAK_INFO("RHW", "RH", LEASE2F2); CHECK_VAL(io2.out.durable_open_v2, false); CHECK_VAL(io2.out.timeout, 0); CHECK_VAL(io2.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 1); - CHECK_PTR(lease_break_info.lease_transport, transport1); + torture_reset_lease_break_info(tctx, &lease_break_info); - unblock_ok = torture_unblock_tcp_transport(tctx, transport2C); - unblock_ok = torture_unblock_tcp_transport(tctx, transport2A); + /* Unblock 2B and 2C */ + torture_comment(tctx, "Unblocking 2B and 2C\n"); unblock_ok = torture_unblock_tcp_transport(tctx, transport2B); + unblock_ok |= torture_unblock_tcp_transport(tctx, transport2C); torture_assert(tctx, unblock_ok, "we could not unblock tcp transport"); + torture_unblock_cleanup(tctx); - /* next test: disconnect 2C and trigger break */ + /* Will this trigger pending break? */ + smb2_keepalive(transport2B); + smb2_keepalive(transport2C); + CHECK_VAL(lease_break_info.count, 0); - torture_reset_lease_break_info(tctx, &lease_break_info); /* - * now add a third channel and repeat the test, we need to reestablish - * transport2C because the remote end has invalidated our connection + * 1 opens file2 + * lease break? */ + torture_comment(tctx, "client opens fname1 via session 1\n"); + + smb2_lease_create(&io1, &ls1, false, fname1, LEASE1F1, + smb2_util_lease_state("RHW")); + status = smb2_create(tree1, mem_ctx, &io1); + CHECK_STATUS(status, NT_STATUS_OK); + h_client1_file1 = io1.out.file.handle; + CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io1, "RH", true, LEASE1F1, 0); + CHECK_BREAK_INFO("RHW", "RH", LEASE2F1); + CHECK_VAL(io1.out.durable_open_v2, false); + CHECK_VAL(io1.out.timeout, 0); + CHECK_VAL(io1.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 1); + + + torture_comment(tctx, "Reconnecting session 2B\n"); + talloc_free(transport2B); + talloc_free(session2B); + talloc_free(tree2B); status = smb2_connect(tctx, host, lpcfg_smb_ports(tctx->lp_ctx), share, lpcfg_resolve_context(tctx->lp_ctx), credentials, - &tree2C, + &tree2B, tctx->ev, &transport2_options, lpcfg_socket_options(tctx->lp_ctx), @@ -1343,66 +1420,185 @@ static bool test_multichannel_lease_break(struct torture_context *tctx, ); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "smb2_connect failed"); - transport2C = tree2C->session->transport; + transport2B = tree2B->session->transport; - torture_comment(tctx, "transport2C [%p]\n", transport2C); - /* - * Now bind the session2 to the transport2C - */ - session2C = smb2_session_channel(transport2C, + session2B = smb2_session_channel(transport2B, lpcfg_gensec_settings(tctx, tctx->lp_ctx), tree2A, session2A); - tree2C->smbXcli = tree2A->smbXcli; - tree2C->session = session2C; + tree2B->smbXcli = tree2A->smbXcli; + tree2B->session = session2B; - torture_assert(tctx, session2C != NULL, "smb2_session_channel failed"); + torture_assert(tctx, session2B != NULL, "smb2_session_channel failed"); - transport2C->lease.handler = torture_lease_handler; - transport2C->lease.private_data = tree2C; - torture_comment(tctx, "transport2C [%p]\n", transport2C); + transport2B->lease.handler = torture_lease_handler; + transport2B->lease.private_data = tree2B; + torture_comment(tctx, "transport2B [%p]\n", transport2B); - torture_comment(tctx, "established transport 2C\n"); + torture_comment(tctx, "established transport 2B\n"); - status = smb2_session_setup_spnego(session2C, + local_port = torture_get_local_port_from_transport(transport2B); + torture_comment(tctx, "transport2B uses tcp port: %d\n", local_port); + + status = smb2_session_setup_spnego(session2B, popt_get_cmdline_credentials(), 0 /* previous_session_id */); CHECK_STATUS(status, NT_STATUS_OK); - torture_comment(tctx, "bound session2C to session2A\n"); + torture_comment(tctx, "bound session2B to session2A\n"); - torture_comment(tctx, "client 2 opening fname3 over newly established transport2C\n"); + torture_comment(tctx, "client closes fname1 via session 2A\n"); + status = smb2_util_close(tree2A, h_client2_file1); + CHECK_STATUS(status, NT_STATUS_OK); + torture_reset_lease_break_info(tctx, &lease_break_info); + smb2_util_close(tree1, h_client1_file1); + smb2_util_close(tree1, h_client1_file2); + smb2_util_close(tree1, h_client1_file3); + smb2_util_close(tree2A, h_client2_file1); + smb2_util_close(tree2A, h_client2_file2); + smb2_util_close(tree2A, h_client2_file3); + + smb2_util_unlink(tree1, fname1); + smb2_util_unlink(tree1, fname2); + smb2_util_unlink(tree1, fname3); + CHECK_VAL(lease_break_info.count, 0); + + /* + * Test 4: + * open file1 in session 2A + * open file2 in session 2B + * open file3 in session 2C + * Disconnect 2C + * open file3 in session 1 + * lease break? + * server allows session 1 to open file1 + * Block 2B + * open file2 in session 1 + * no oplock break because 2B blocked. + * session 1 allowed to open file2 + * 2A writes "Here I am to file 2" + * Recieve break on 1 drop oplock. + */ + torture_comment(tctx, "Test 4 start \n"); + + /* 2a opens file1 */ + torture_comment(tctx, "client2 opens fname1 via session 2A\n"); + smb2_lease_create(&io1, &ls1, false, fname1, LEASE2F1, + smb2_util_lease_state("RHW")); + status = smb2_create(tree2A, mem_ctx, &io1); + CHECK_STATUS(status, NT_STATUS_OK); + h_client2_file1 = io1.out.file.handle; + CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io1, "RHW", true, LEASE2F1, 0); + CHECK_VAL(io1.out.durable_open_v2, false); //true); + CHECK_VAL(io1.out.timeout, io1.in.timeout); + CHECK_VAL(io1.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 0); + + /* 2b opens file2 */ + torture_comment(tctx, "client2 opens fname2 via session 2B\n"); + smb2_lease_create(&io2, &ls2, false, fname2, LEASE2F2, + smb2_util_lease_state("RHW")); + status = smb2_create(tree2B, mem_ctx, &io2); + CHECK_STATUS(status, NT_STATUS_OK); + h_client2_file2 = io2.out.file.handle; + CHECK_CREATED(&io2, CREATED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io2, "RHW", true, LEASE2F2, 0); + CHECK_VAL(io2.out.durable_open_v2, false); //true); + CHECK_VAL(io2.out.timeout, io2.in.timeout); + CHECK_VAL(io2.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 0); + + /* 2c opens file3 */ + torture_comment(tctx, "client2 opens fname3 via session 2C\n"); + smb2_lease_create(&io3, &ls3, false, fname3, LEASE2F3, + smb2_util_lease_state("RHW")); status = smb2_create(tree2C, mem_ctx, &io3); CHECK_STATUS(status, NT_STATUS_OK); h_client2_file3 = io3.out.file.handle; CHECK_CREATED(&io3, CREATED, FILE_ATTRIBUTE_ARCHIVE); - CHECK_VAL(io3.out.oplock_level, smb2_util_oplock_level("b")); - CHECK_VAL(io3.out.durable_open_v2, true); - CHECK_VAL(io3.out.timeout, io3.in.timeout); + CHECK_LEASE(&io3, "RHW", true, LEASE2F3, 0); + CHECK_VAL(io3.out.durable_open_v2, false); + CHECK_VAL(io3.out.timeout, io2.in.timeout); CHECK_VAL(io3.out.durable_open, false); - CHECK_VAL(break_info.count, 0); + CHECK_VAL(lease_break_info.count, 0); + /* Disconnect 2C */ + torture_comment(tctx, "Disconnect 2C\n"); torture_comment(tctx, "explicit disconnect of transport2C\n"); smbXcli_conn_disconnect(transport2C->conn, NT_STATUS_FOOBAR); - torture_comment(tctx, "client1 opens fname3 via session 1\n"); - + /* + * 1 opens file3 + * batchoplock break? + */ + torture_comment(tctx, "Client opens fname3 with session 1\n"); + smb2_lease_create(&io3, &ls3, false, fname3, LEASE1F3, + smb2_util_lease_state("RHW")); status = smb2_create(tree1, mem_ctx, &io3); CHECK_STATUS(status, NT_STATUS_OK); h_client1_file3 = io3.out.file.handle; CHECK_CREATED(&io3, EXISTED, FILE_ATTRIBUTE_ARCHIVE); - CHECK_VAL(io3.out.oplock_level, smb2_util_oplock_level("s")); - CHECK_VAL(io3.out.durable_open_v2, false); - CHECK_VAL(io3.out.timeout, 0); - CHECK_VAL(io3.out.durable_open, false); + CHECK_LEASE(&io3, "RH", true, LEASE1F3, 0); + CHECK_BREAK_INFO("RHW", "RH", LEASE2F3); + CHECK_VAL(io1.out.durable_open_v2, false); + CHECK_VAL(io1.out.timeout, 0); + CHECK_VAL(io1.out.durable_open, false); CHECK_VAL(lease_break_info.count, 1); - CHECK_PTR(lease_break_info.lease_transport, transport2B); - if (h != NULL) { - smb2_util_close(tree1, *h); - h = NULL; - } + torture_reset_lease_break_info(tctx, &lease_break_info); + + /* Block 2B */ + block_ok = torture_block_tcp_transport(tctx, transport2B); + torture_assert(tctx, block_ok, "we could not block tcp transport"); + + /* + * 1 opens file2 + * batchoplock break? + */ + torture_comment(tctx, "client opens fname2 via session 1\n"); + smb2_lease_create(&io2, &ls2, false, fname2, LEASE1F2, + smb2_util_lease_state("RHW")); + status = smb2_create(tree1, mem_ctx, &io2); + CHECK_STATUS(status, NT_STATUS_OK); + h_client1_file2 = io2.out.file.handle; + CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE); + CHECK_LEASE(&io2, "RH", true, LEASE1F2, 0); + CHECK_BREAK_INFO("RHW", "RH", LEASE2F2); + CHECK_VAL(io2.out.durable_open_v2, false); + CHECK_VAL(io2.out.timeout, 0); + CHECK_VAL(io2.out.durable_open, false); + CHECK_VAL(lease_break_info.count, 1); + + /* 2A writes "Here I am to file 2" */ + + torture_comment(tctx, "Trying write to file2 on tree2A\n"); + blob = data_blob_string_const("Here I am"); + status = smb2_util_write(tree2A, + h_client2_file2, + blob.data, + 0, + blob.length); + torture_assert_ntstatus_ok(tctx, status, + "failed to write file2 via channel 2A"); + + /* Unblock 2B */ + unblock_ok = torture_unblock_tcp_transport(tctx, transport2B); + torture_assert(tctx, unblock_ok, "we could not unblock tcp transport"); + + torture_reset_lease_break_info(tctx, &lease_break_info); + smb2_util_close(tree1, h_client1_file1); + smb2_util_close(tree1, h_client1_file2); + smb2_util_close(tree1, h_client1_file3); + smb2_util_close(tree2A, h_client2_file1); + smb2_util_close(tree2A, h_client2_file2); + smb2_util_close(tree2A, h_client2_file3); + + smb2_util_unlink(tree1, fname1); + smb2_util_unlink(tree1, fname2); + smb2_util_unlink(tree1, fname3); + CHECK_VAL(lease_break_info.count, 0); done: if (block_ok && !unblock_ok) {