From 15e1c610273766a548a28b4d8731c6e9bad4496e Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 3 Dec 2009 13:46:11 -0800 Subject: s4 torture: Add a new RAW-OPLOCK test: BATCH26 Try a rename with a wide-open share mode on an already open file and the there is still share mode contention. For the reason why see: http://social.msdn.microsoft.com/Forums/en-US/os_fileservices/thread/3ca14dc9-da1f-4786-a8f7-a86e9903db0c Msft's anser: After further review, The reason for server to fail with sharing violation is that the windows server that executes a path-based rename request opens the file for DELETE access, but only with FILE_SHARED_READ as ShareAccess . Therefore, the existing open(frame 76), which has shared read/write/delete , is compatible with the Windows servers access mode (DELETE), but Windows servers open is not compatible with access mode in existing open. Note that it is correct to state that the logic in Windows server could have been written to allow shared read/write/delete in which case it would succeed as you mention. The behavior here is historical based on the existing implementation. --- source4/torture/raw/oplock.c | 108 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'source4/torture') diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c index d35445c7eb..78987e3121 100644 --- a/source4/torture/raw/oplock.c +++ b/source4/torture/raw/oplock.c @@ -2969,6 +2969,113 @@ done: return ret; } +/** + * Similar to batch17/18, but test with open share mode rather than + * share_none. + */ +static bool test_raw_oplock_batch26(struct torture_context *tctx, + struct smbcli_state *cli1, struct smbcli_state *cli2) +{ + const char *fname1 = BASEDIR "\\test_batch26_1.dat"; + const char *fname2 = BASEDIR "\\test_batch26_2.dat"; + NTSTATUS status; + bool ret = true; + union smb_open io; + union smb_rename rn; + uint16_t fnum=0; + + if (!torture_setup_dir(cli1, BASEDIR)) { + return false; + } + + /* cleanup */ + smbcli_unlink(cli1->tree, fname1); + smbcli_unlink(cli1->tree, fname2); + + 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_READ | + NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE; + 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 = fname1; + + torture_comment(tctx, "BATCH26: open a file with an batch oplock " + "(share mode: none)\n"); + + ZERO_STRUCT(break_info); + io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | + NTCREATEX_FLAGS_REQUEST_OPLOCK | + NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; + + + 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.oplock_level, BATCH_OPLOCK_RETURN); + + torture_comment(tctx, "rename should trigger a break\n"); + ZERO_STRUCT(rn); + rn.generic.level = RAW_RENAME_RENAME; + rn.rename.in.pattern1 = fname1; + rn.rename.in.pattern2 = fname2; + rn.rename.in.attrib = 0; + + torture_comment(tctx, "trying rename while first file open\n"); + status = smb_raw_rename(cli2->tree, &rn); + CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION); + + torture_wait_for_oplock_break(tctx); + CHECK_VAL(break_info.count, 1); + CHECK_VAL(break_info.failures, 0); + CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II); + + /* Close and reopen with batch again. */ + smbcli_close(cli1->tree, fnum); + ZERO_STRUCT(break_info); + + 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.oplock_level, BATCH_OPLOCK_RETURN); + + /* Now try ntrename. */ + torture_comment(tctx, "ntrename should trigger a break\n"); + ZERO_STRUCT(rn); + rn.generic.level = RAW_RENAME_NTRENAME; + rn.ntrename.in.attrib = 0; + rn.ntrename.in.flags = RENAME_FLAG_RENAME; + rn.ntrename.in.old_name = fname1; + rn.ntrename.in.new_name = fname2; + torture_comment(tctx, "trying rename while first file open\n"); + status = smb_raw_rename(cli2->tree, &rn); + CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION); + + torture_wait_for_oplock_break(tctx); + CHECK_VAL(break_info.count, 1); + CHECK_VAL(break_info.failures, 0); + CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II); + + smbcli_close(cli1->tree, fnum); + +done: + smb_raw_exit(cli1->session); + smb_raw_exit(cli2->session); + smbcli_deltree(cli1->tree, BASEDIR); + return ret; +} + /* Test how oplocks work on streams. */ static bool test_raw_oplock_stream1(struct torture_context *tctx, struct smbcli_state *cli1, @@ -3557,6 +3664,7 @@ struct torture_suite *torture_raw_oplock(TALLOC_CTX *mem_ctx) torture_suite_add_2smb_test(suite, "BATCH23", test_raw_oplock_batch23); torture_suite_add_2smb_test(suite, "BATCH24", test_raw_oplock_batch24); torture_suite_add_2smb_test(suite, "BATCH25", test_raw_oplock_batch25); + torture_suite_add_2smb_test(suite, "BATCH26", test_raw_oplock_batch26); torture_suite_add_2smb_test(suite, "STREAM1", test_raw_oplock_stream1); torture_suite_add_1smb_test(suite, "DOC1", test_raw_oplock_doc); torture_suite_add_2smb_test(suite, "BRL1", test_raw_oplock_brl1); -- cgit