2 Unix SMB/CIFS implementation.
3 basic raw test suite for oplocks
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "torture/torture.h"
22 #include "librpc/gen_ndr/security.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/libcli.h"
25 #include "torture/util.h"
26 #include "lib/events/events.h"
28 #define CHECK_VAL(v, correct) do { \
29 if ((v) != (correct)) { \
30 torture_result(tctx, TORTURE_FAIL, __location__": wrong value for %s got 0x%x - should be 0x%x", \
31 #v, (int)v, (int)correct); \
35 #define CHECK_STATUS(tctx, status, correct) do { \
36 if (!NT_STATUS_EQUAL(status, correct)) { \
37 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
38 nt_errstr(status), nt_errstr(correct)); \
51 #define BASEDIR "\\test_oplock"
54 a handler function for oplock break requests. Ack it as a break to level II if possible
56 static BOOL oplock_handler_ack_to_levelII(struct smbcli_transport *transport, uint16_t tid,
57 uint16_t fnum, uint8_t level, void *private)
59 struct smbcli_tree *tree = private;
60 break_info.fnum = fnum;
61 break_info.level = level;
64 printf("Acking to level II in oplock handler\n");
66 return smbcli_oplock_ack(tree, fnum, level);
70 a handler function for oplock break requests. Ack it as a break to none
72 static BOOL oplock_handler_ack_to_none(struct smbcli_transport *transport, uint16_t tid,
73 uint16_t fnum, uint8_t level,
76 struct smbcli_tree *tree = private;
77 break_info.fnum = fnum;
78 break_info.level = level;
81 printf("Acking to none in oplock handler\n");
83 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
86 static void oplock_handler_close_recv(struct smbcli_request *req)
89 status = smbcli_request_simple_recv(req);
90 if (!NT_STATUS_IS_OK(status)) {
91 printf("close failed in oplock_handler_close\n");
92 break_info.failures++;
97 a handler function for oplock break requests - close the file
99 static BOOL oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
100 uint16_t fnum, uint8_t level, void *private)
103 struct smbcli_tree *tree = private;
104 struct smbcli_request *req;
106 break_info.fnum = fnum;
107 break_info.level = level;
110 io.close.level = RAW_CLOSE_CLOSE;
111 io.close.in.file.fnum = fnum;
112 io.close.in.write_time = 0;
113 req = smb_raw_close_send(tree, &io);
115 printf("failed to send close in oplock_handler_close\n");
119 req->async.fn = oplock_handler_close_recv;
120 req->async.private = NULL;
125 static bool test_raw_oplock_normal(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
127 const char *fname = BASEDIR "\\test_normal.dat";
131 union smb_unlink unl;
134 if (!torture_setup_dir(cli1, BASEDIR)) {
139 smbcli_unlink(cli1->tree, fname);
141 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
146 io.generic.level = RAW_OPEN_NTCREATEX;
147 io.ntcreatex.in.root_fid = 0;
148 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
149 io.ntcreatex.in.alloc_size = 0;
150 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
151 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
152 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
153 io.ntcreatex.in.create_options = 0;
154 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
155 io.ntcreatex.in.security_flags = 0;
156 io.ntcreatex.in.fname = fname;
158 torture_comment(tctx, "open a file with a normal oplock\n");
159 ZERO_STRUCT(break_info);
160 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
162 status = smb_raw_open(cli1->tree, tctx, &io);
163 CHECK_STATUS(tctx, status, NT_STATUS_OK);
164 fnum = io.ntcreatex.out.file.fnum;
165 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
167 torture_comment(tctx, "a 2nd open should not cause a break\n");
168 status = smb_raw_open(cli2->tree, tctx, &io);
169 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
170 CHECK_VAL(break_info.count, 0);
171 CHECK_VAL(break_info.failures, 0);
173 torture_comment(tctx, "unlink it - should also be no break\n");
174 unl.unlink.in.pattern = fname;
175 unl.unlink.in.attrib = 0;
176 status = smb_raw_unlink(cli2->tree, &unl);
177 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
178 CHECK_VAL(break_info.count, 0);
179 CHECK_VAL(break_info.failures, 0);
181 smbcli_close(cli1->tree, fnum);
184 smb_raw_exit(cli1->session);
185 smb_raw_exit(cli2->session);
186 smbcli_deltree(cli1->tree, BASEDIR);
190 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
192 const char *fname = BASEDIR "\\test_batch1.dat";
196 union smb_unlink unl;
200 if (!torture_setup_dir(cli1, BASEDIR)) {
205 smbcli_unlink(cli1->tree, fname);
207 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
212 io.generic.level = RAW_OPEN_NTCREATEX;
213 io.ntcreatex.in.root_fid = 0;
214 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
215 io.ntcreatex.in.alloc_size = 0;
216 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
217 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
218 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
219 io.ntcreatex.in.create_options = 0;
220 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
221 io.ntcreatex.in.security_flags = 0;
222 io.ntcreatex.in.fname = fname;
225 with a batch oplock we get a break
227 torture_comment(tctx, "open with batch oplock\n");
228 ZERO_STRUCT(break_info);
229 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
230 NTCREATEX_FLAGS_REQUEST_OPLOCK |
231 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
232 status = smb_raw_open(cli1->tree, tctx, &io);
233 CHECK_STATUS(tctx, status, NT_STATUS_OK);
234 fnum = io.ntcreatex.out.file.fnum;
235 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
237 torture_comment(tctx, "unlink should generate a break\n");
238 unl.unlink.in.pattern = fname;
239 unl.unlink.in.attrib = 0;
240 status = smb_raw_unlink(cli2->tree, &unl);
241 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
243 CHECK_VAL(break_info.count, 1);
244 CHECK_VAL(break_info.fnum, fnum);
245 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
246 CHECK_VAL(break_info.failures, 0);
248 torture_comment(tctx, "2nd unlink should not generate a break\n");
249 ZERO_STRUCT(break_info);
250 status = smb_raw_unlink(cli2->tree, &unl);
251 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
253 CHECK_VAL(break_info.count, 0);
255 torture_comment(tctx, "writing should generate a self break to none\n");
256 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
258 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
260 CHECK_VAL(break_info.count, 1);
261 CHECK_VAL(break_info.fnum, fnum);
262 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
263 CHECK_VAL(break_info.failures, 0);
265 smbcli_close(cli1->tree, fnum);
268 smb_raw_exit(cli1->session);
269 smb_raw_exit(cli2->session);
270 smbcli_deltree(cli1->tree, BASEDIR);
274 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
276 const char *fname = BASEDIR "\\test_batch2.dat";
280 union smb_unlink unl;
284 if (!torture_setup_dir(cli1, BASEDIR)) {
289 smbcli_unlink(cli1->tree, fname);
291 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
296 io.generic.level = RAW_OPEN_NTCREATEX;
297 io.ntcreatex.in.root_fid = 0;
298 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
299 io.ntcreatex.in.alloc_size = 0;
300 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
301 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
302 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
303 io.ntcreatex.in.create_options = 0;
304 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
305 io.ntcreatex.in.security_flags = 0;
306 io.ntcreatex.in.fname = fname;
308 torture_comment(tctx, "open with batch oplock\n");
309 ZERO_STRUCT(break_info);
310 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
311 NTCREATEX_FLAGS_REQUEST_OPLOCK |
312 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
313 status = smb_raw_open(cli1->tree, tctx, &io);
314 CHECK_STATUS(tctx, status, NT_STATUS_OK);
315 fnum = io.ntcreatex.out.file.fnum;
316 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
318 torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
319 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
320 unl.unlink.in.pattern = fname;
321 unl.unlink.in.attrib = 0;
322 status = smb_raw_unlink(cli2->tree, &unl);
323 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
325 CHECK_VAL(break_info.count, 1);
326 CHECK_VAL(break_info.fnum, fnum);
327 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
328 CHECK_VAL(break_info.failures, 0);
330 torture_comment(tctx, "2nd unlink should not generate a break\n");
331 ZERO_STRUCT(break_info);
332 status = smb_raw_unlink(cli2->tree, &unl);
333 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
335 CHECK_VAL(break_info.count, 0);
337 torture_comment(tctx, "writing should not generate a break\n");
338 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
340 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
342 CHECK_VAL(break_info.count, 0);
344 smbcli_close(cli1->tree, fnum);
347 smb_raw_exit(cli1->session);
348 smb_raw_exit(cli2->session);
349 smbcli_deltree(cli1->tree, BASEDIR);
353 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
355 const char *fname = BASEDIR "\\test_batch3.dat";
359 union smb_unlink unl;
362 if (!torture_setup_dir(cli1, BASEDIR)) {
367 smbcli_unlink(cli1->tree, fname);
369 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
374 io.generic.level = RAW_OPEN_NTCREATEX;
375 io.ntcreatex.in.root_fid = 0;
376 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
377 io.ntcreatex.in.alloc_size = 0;
378 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
379 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
380 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
381 io.ntcreatex.in.create_options = 0;
382 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
383 io.ntcreatex.in.security_flags = 0;
384 io.ntcreatex.in.fname = fname;
386 torture_comment(tctx, "if we close on break then the unlink can succeed\n");
387 ZERO_STRUCT(break_info);
388 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
389 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
390 NTCREATEX_FLAGS_REQUEST_OPLOCK |
391 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
392 status = smb_raw_open(cli1->tree, tctx, &io);
393 CHECK_STATUS(tctx, status, NT_STATUS_OK);
394 fnum = io.ntcreatex.out.file.fnum;
395 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
397 unl.unlink.in.pattern = fname;
398 unl.unlink.in.attrib = 0;
399 ZERO_STRUCT(break_info);
400 status = smb_raw_unlink(cli2->tree, &unl);
401 CHECK_STATUS(tctx, status, NT_STATUS_OK);
403 CHECK_VAL(break_info.count, 1);
404 CHECK_VAL(break_info.fnum, fnum);
405 CHECK_VAL(break_info.level, 1);
406 CHECK_VAL(break_info.failures, 0);
408 smbcli_close(cli1->tree, fnum);
411 smb_raw_exit(cli1->session);
412 smb_raw_exit(cli2->session);
413 smbcli_deltree(cli1->tree, BASEDIR);
417 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
419 const char *fname = BASEDIR "\\test_batch4.dat";
426 if (!torture_setup_dir(cli1, BASEDIR)) {
431 smbcli_unlink(cli1->tree, fname);
433 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
438 io.generic.level = RAW_OPEN_NTCREATEX;
439 io.ntcreatex.in.root_fid = 0;
440 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
441 io.ntcreatex.in.alloc_size = 0;
442 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
443 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
444 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
445 io.ntcreatex.in.create_options = 0;
446 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
447 io.ntcreatex.in.security_flags = 0;
448 io.ntcreatex.in.fname = fname;
450 torture_comment(tctx, "a self read should not cause a break\n");
451 ZERO_STRUCT(break_info);
452 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
454 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
455 NTCREATEX_FLAGS_REQUEST_OPLOCK |
456 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
457 status = smb_raw_open(cli1->tree, tctx, &io);
458 CHECK_STATUS(tctx, status, NT_STATUS_OK);
459 fnum = io.ntcreatex.out.file.fnum;
460 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
462 rd.read.level = RAW_READ_READ;
463 rd.read.in.file.fnum = fnum;
464 rd.read.in.count = 1;
465 rd.read.in.offset = 0;
466 rd.read.in.remaining = 0;
467 status = smb_raw_read(cli1->tree, &rd);
468 CHECK_STATUS(tctx, status, NT_STATUS_OK);
469 CHECK_VAL(break_info.count, 0);
470 CHECK_VAL(break_info.failures, 0);
472 smbcli_close(cli1->tree, fnum);
475 smb_raw_exit(cli1->session);
476 smb_raw_exit(cli2->session);
477 smbcli_deltree(cli1->tree, BASEDIR);
481 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
483 const char *fname = BASEDIR "\\test_batch5.dat";
489 if (!torture_setup_dir(cli1, BASEDIR)) {
494 smbcli_unlink(cli1->tree, fname);
496 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
501 io.generic.level = RAW_OPEN_NTCREATEX;
502 io.ntcreatex.in.root_fid = 0;
503 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
504 io.ntcreatex.in.alloc_size = 0;
505 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
506 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
507 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
508 io.ntcreatex.in.create_options = 0;
509 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
510 io.ntcreatex.in.security_flags = 0;
511 io.ntcreatex.in.fname = fname;
513 torture_comment(tctx, "a 2nd open should give a break\n");
514 ZERO_STRUCT(break_info);
515 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
517 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
518 NTCREATEX_FLAGS_REQUEST_OPLOCK |
519 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
520 status = smb_raw_open(cli1->tree, tctx, &io);
521 CHECK_STATUS(tctx, status, NT_STATUS_OK);
522 fnum = io.ntcreatex.out.file.fnum;
523 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
525 ZERO_STRUCT(break_info);
527 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
528 status = smb_raw_open(cli2->tree, tctx, &io);
529 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
531 CHECK_VAL(break_info.count, 1);
532 CHECK_VAL(break_info.fnum, fnum);
533 CHECK_VAL(break_info.level, 1);
534 CHECK_VAL(break_info.failures, 0);
536 smbcli_close(cli1->tree, fnum);
539 smb_raw_exit(cli1->session);
540 smb_raw_exit(cli2->session);
541 smbcli_deltree(cli1->tree, BASEDIR);
545 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
547 const char *fname = BASEDIR "\\test_batch6.dat";
551 uint16_t fnum=0, fnum2=0;
554 if (!torture_setup_dir(cli1, BASEDIR)) {
559 smbcli_unlink(cli1->tree, fname);
561 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
566 io.generic.level = RAW_OPEN_NTCREATEX;
567 io.ntcreatex.in.root_fid = 0;
568 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
569 io.ntcreatex.in.alloc_size = 0;
570 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
571 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
572 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
573 io.ntcreatex.in.create_options = 0;
574 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
575 io.ntcreatex.in.security_flags = 0;
576 io.ntcreatex.in.fname = fname;
578 torture_comment(tctx, "a 2nd open should give a break to level II if the first open allowed shared read\n");
579 ZERO_STRUCT(break_info);
580 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
581 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli2->tree);
583 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
584 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
585 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
586 NTCREATEX_FLAGS_REQUEST_OPLOCK |
587 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
588 status = smb_raw_open(cli1->tree, tctx, &io);
589 CHECK_STATUS(tctx, status, NT_STATUS_OK);
590 fnum = io.ntcreatex.out.file.fnum;
591 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
593 ZERO_STRUCT(break_info);
595 status = smb_raw_open(cli2->tree, tctx, &io);
596 CHECK_STATUS(tctx, status, NT_STATUS_OK);
597 fnum2 = io.ntcreatex.out.file.fnum;
598 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
600 CHECK_VAL(break_info.count, 1);
601 CHECK_VAL(break_info.fnum, fnum);
602 CHECK_VAL(break_info.level, 1);
603 CHECK_VAL(break_info.failures, 0);
604 ZERO_STRUCT(break_info);
606 torture_comment(tctx, "write should trigger a break to none on both\n");
607 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
609 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
611 CHECK_VAL(break_info.count, 2);
612 CHECK_VAL(break_info.level, 0);
613 CHECK_VAL(break_info.failures, 0);
615 smbcli_close(cli1->tree, fnum);
616 smbcli_close(cli2->tree, fnum2);
620 smb_raw_exit(cli1->session);
621 smb_raw_exit(cli2->session);
622 smbcli_deltree(cli1->tree, BASEDIR);
626 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
628 const char *fname = BASEDIR "\\test_batch7.dat";
632 uint16_t fnum=0, fnum2=0;
634 if (!torture_setup_dir(cli1, BASEDIR)) {
639 smbcli_unlink(cli1->tree, fname);
641 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
646 io.generic.level = RAW_OPEN_NTCREATEX;
647 io.ntcreatex.in.root_fid = 0;
648 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
649 io.ntcreatex.in.alloc_size = 0;
650 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
651 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
652 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
653 io.ntcreatex.in.create_options = 0;
654 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
655 io.ntcreatex.in.security_flags = 0;
656 io.ntcreatex.in.fname = fname;
658 torture_comment(tctx, "a 2nd open should get an oplock when we close instead of ack\n");
659 ZERO_STRUCT(break_info);
660 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
662 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
663 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
664 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
665 NTCREATEX_FLAGS_REQUEST_OPLOCK |
666 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
667 status = smb_raw_open(cli1->tree, tctx, &io);
668 CHECK_STATUS(tctx, status, NT_STATUS_OK);
669 fnum2 = io.ntcreatex.out.file.fnum;
670 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
672 ZERO_STRUCT(break_info);
674 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
675 NTCREATEX_FLAGS_REQUEST_OPLOCK |
676 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
677 status = smb_raw_open(cli2->tree, tctx, &io);
678 CHECK_STATUS(tctx, status, NT_STATUS_OK);
679 fnum = io.ntcreatex.out.file.fnum;
680 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
682 CHECK_VAL(break_info.count, 1);
683 CHECK_VAL(break_info.fnum, fnum2);
684 CHECK_VAL(break_info.level, 1);
685 CHECK_VAL(break_info.failures, 0);
687 smbcli_close(cli2->tree, fnum);
690 smb_raw_exit(cli1->session);
691 smb_raw_exit(cli2->session);
692 smbcli_deltree(cli1->tree, BASEDIR);
696 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
698 const char *fname = BASEDIR "\\test_batch8.dat";
702 uint16_t fnum=0, fnum2=0;
704 if (!torture_setup_dir(cli1, BASEDIR)) {
709 smbcli_unlink(cli1->tree, fname);
711 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
716 io.generic.level = RAW_OPEN_NTCREATEX;
717 io.ntcreatex.in.root_fid = 0;
718 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
719 io.ntcreatex.in.alloc_size = 0;
720 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
721 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
722 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
723 io.ntcreatex.in.create_options = 0;
724 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
725 io.ntcreatex.in.security_flags = 0;
726 io.ntcreatex.in.fname = fname;
728 torture_comment(tctx, "open with batch oplock\n");
729 ZERO_STRUCT(break_info);
730 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
732 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
733 NTCREATEX_FLAGS_REQUEST_OPLOCK |
734 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
735 status = smb_raw_open(cli1->tree, tctx, &io);
736 CHECK_STATUS(tctx, status, NT_STATUS_OK);
737 fnum = io.ntcreatex.out.file.fnum;
738 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
740 ZERO_STRUCT(break_info);
741 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
743 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
744 NTCREATEX_FLAGS_REQUEST_OPLOCK |
745 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
746 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
747 status = smb_raw_open(cli2->tree, tctx, &io);
748 CHECK_STATUS(tctx, status, NT_STATUS_OK);
749 fnum2 = io.ntcreatex.out.file.fnum;
750 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
751 CHECK_VAL(break_info.count, 0);
752 CHECK_VAL(break_info.failures, 0);
754 smbcli_close(cli1->tree, fnum);
755 smbcli_close(cli2->tree, fnum2);
758 smb_raw_exit(cli1->session);
759 smb_raw_exit(cli2->session);
760 smbcli_deltree(cli1->tree, BASEDIR);
764 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
766 const char *fname = BASEDIR "\\test_batch9.dat";
770 uint16_t fnum=0, fnum2=0;
773 if (!torture_setup_dir(cli1, BASEDIR)) {
778 smbcli_unlink(cli1->tree, fname);
780 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
785 io.generic.level = RAW_OPEN_NTCREATEX;
786 io.ntcreatex.in.root_fid = 0;
787 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
788 io.ntcreatex.in.alloc_size = 0;
789 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
790 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
791 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
792 io.ntcreatex.in.create_options = 0;
793 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
794 io.ntcreatex.in.security_flags = 0;
795 io.ntcreatex.in.fname = fname;
797 torture_comment(tctx, "open with attributes only can create file\n");
799 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
800 NTCREATEX_FLAGS_REQUEST_OPLOCK |
801 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
802 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
803 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
804 status = smb_raw_open(cli1->tree, tctx, &io);
805 CHECK_STATUS(tctx, status, NT_STATUS_OK);
806 fnum = io.ntcreatex.out.file.fnum;
807 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
809 torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
811 ZERO_STRUCT(break_info);
812 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
814 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
815 NTCREATEX_FLAGS_REQUEST_OPLOCK |
816 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
817 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
818 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
819 status = smb_raw_open(cli2->tree, tctx, &io);
820 CHECK_STATUS(tctx, status, NT_STATUS_OK);
821 fnum2 = io.ntcreatex.out.file.fnum;
822 CHECK_VAL(break_info.count, 1);
823 CHECK_VAL(break_info.fnum, fnum);
824 CHECK_VAL(break_info.failures, 0);
825 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
826 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
827 smbcli_close(cli2->tree, fnum2);
829 torture_comment(tctx, "third oplocked open should grant level2 without break\n");
830 ZERO_STRUCT(break_info);
831 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
832 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli2->tree);
833 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
834 NTCREATEX_FLAGS_REQUEST_OPLOCK |
835 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
836 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
837 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
838 status = smb_raw_open(cli2->tree, tctx, &io);
839 CHECK_STATUS(tctx, status, NT_STATUS_OK);
840 fnum2 = io.ntcreatex.out.file.fnum;
841 CHECK_VAL(break_info.count, 0);
842 CHECK_VAL(break_info.failures, 0);
843 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
845 ZERO_STRUCT(break_info);
847 torture_comment(tctx, "write should trigger a break to none on both\n");
848 smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
850 /* Now the oplock break request comes in. But right now we can't
851 * answer it. Do another write */
854 smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
856 CHECK_VAL(break_info.count, 2);
857 CHECK_VAL(break_info.level, 0);
858 CHECK_VAL(break_info.failures, 0);
860 smbcli_close(cli1->tree, fnum);
861 smbcli_close(cli2->tree, fnum2);
864 smb_raw_exit(cli1->session);
865 smb_raw_exit(cli2->session);
866 smbcli_deltree(cli1->tree, BASEDIR);
870 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
872 const char *fname = BASEDIR "\\test_batch10.dat";
876 uint16_t fnum=0, fnum2=0;
878 if (!torture_setup_dir(cli1, BASEDIR)) {
883 smbcli_unlink(cli1->tree, fname);
885 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
890 io.generic.level = RAW_OPEN_NTCREATEX;
891 io.ntcreatex.in.root_fid = 0;
892 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
893 io.ntcreatex.in.alloc_size = 0;
894 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
895 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
896 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
897 io.ntcreatex.in.create_options = 0;
898 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
899 io.ntcreatex.in.security_flags = 0;
900 io.ntcreatex.in.fname = fname;
902 torture_comment(tctx, "Open with oplock after a non-oplock open should grant level2\n");
903 ZERO_STRUCT(break_info);
904 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
905 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
906 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
907 NTCREATEX_SHARE_ACCESS_WRITE|
908 NTCREATEX_SHARE_ACCESS_DELETE;
909 status = smb_raw_open(cli1->tree, tctx, &io);
910 CHECK_STATUS(tctx, status, NT_STATUS_OK);
911 fnum = io.ntcreatex.out.file.fnum;
912 CHECK_VAL(break_info.count, 0);
913 CHECK_VAL(break_info.failures, 0);
914 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
916 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli1->tree);
918 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
919 NTCREATEX_FLAGS_REQUEST_OPLOCK |
920 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
921 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
922 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
923 NTCREATEX_SHARE_ACCESS_WRITE|
924 NTCREATEX_SHARE_ACCESS_DELETE;
925 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
926 status = smb_raw_open(cli2->tree, tctx, &io);
927 CHECK_STATUS(tctx, status, NT_STATUS_OK);
928 fnum2 = io.ntcreatex.out.file.fnum;
929 CHECK_VAL(break_info.count, 0);
930 CHECK_VAL(break_info.failures, 0);
931 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
933 torture_comment(tctx, "write should trigger a break to none\n");
936 wr.write.level = RAW_WRITE_WRITE;
937 wr.write.in.file.fnum = fnum;
938 wr.write.in.count = 1;
939 wr.write.in.offset = 0;
940 wr.write.in.remaining = 0;
941 wr.write.in.data = (const uint8_t *)"x";
942 status = smb_raw_write(cli1->tree, &wr);
943 CHECK_STATUS(tctx, status, NT_STATUS_OK);
946 /* Now the oplock break request comes in. But right now we can't
947 * answer it. Do another write */
953 wr.write.level = RAW_WRITE_WRITE;
954 wr.write.in.file.fnum = fnum;
955 wr.write.in.count = 1;
956 wr.write.in.offset = 0;
957 wr.write.in.remaining = 0;
958 wr.write.in.data = (const uint8_t *)"x";
959 status = smb_raw_write(cli1->tree, &wr);
960 CHECK_STATUS(tctx, status, NT_STATUS_OK);
963 CHECK_VAL(break_info.count, 1);
964 CHECK_VAL(break_info.fnum, fnum2);
965 CHECK_VAL(break_info.level, 0);
966 CHECK_VAL(break_info.failures, 0);
968 smbcli_close(cli1->tree, fnum);
969 smbcli_close(cli2->tree, fnum2);
972 smb_raw_exit(cli1->session);
973 smb_raw_exit(cli2->session);
974 smbcli_deltree(cli1->tree, BASEDIR);
978 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
980 const char *fname = BASEDIR "\\test_batch11.dat";
984 union smb_setfileinfo sfi;
987 if (!torture_setup_dir(cli1, BASEDIR)) {
992 smbcli_unlink(cli1->tree, fname);
994 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
999 io.generic.level = RAW_OPEN_NTCREATEX;
1000 io.ntcreatex.in.root_fid = 0;
1001 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1002 io.ntcreatex.in.alloc_size = 0;
1003 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1004 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1005 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1006 io.ntcreatex.in.create_options = 0;
1007 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1008 io.ntcreatex.in.security_flags = 0;
1009 io.ntcreatex.in.fname = fname;
1011 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1012 torture_comment(tctx, "Test if setpathinfo set EOF breaks oplocks.\n");
1014 ZERO_STRUCT(break_info);
1015 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1017 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1018 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1019 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1020 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1021 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1022 NTCREATEX_SHARE_ACCESS_WRITE|
1023 NTCREATEX_SHARE_ACCESS_DELETE;
1024 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1025 status = smb_raw_open(cli1->tree, tctx, &io);
1026 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1027 fnum = io.ntcreatex.out.file.fnum;
1028 CHECK_VAL(break_info.count, 0);
1029 CHECK_VAL(break_info.failures, 0);
1030 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1033 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1034 sfi.generic.in.file.path = fname;
1035 sfi.end_of_file_info.in.size = 100;
1037 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1039 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1040 CHECK_VAL(break_info.count, 1);
1041 CHECK_VAL(break_info.failures, 0);
1042 CHECK_VAL(break_info.level, 0);
1044 smbcli_close(cli1->tree, fnum);
1047 smb_raw_exit(cli1->session);
1048 smb_raw_exit(cli2->session);
1049 smbcli_deltree(cli1->tree, BASEDIR);
1053 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1055 const char *fname = BASEDIR "\\test_batch12.dat";
1059 union smb_setfileinfo sfi;
1060 uint16_t fnum=0, fnum2=0;
1062 if (!torture_setup_dir(cli1, BASEDIR)) {
1067 smbcli_unlink(cli1->tree, fname);
1069 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1072 base ntcreatex parms
1074 io.generic.level = RAW_OPEN_NTCREATEX;
1075 io.ntcreatex.in.root_fid = 0;
1076 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1077 io.ntcreatex.in.alloc_size = 0;
1078 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1079 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1080 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1081 io.ntcreatex.in.create_options = 0;
1082 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1083 io.ntcreatex.in.security_flags = 0;
1084 io.ntcreatex.in.fname = fname;
1086 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1087 torture_comment(tctx, "Test if setpathinfo allocation size breaks oplocks.\n");
1089 ZERO_STRUCT(break_info);
1090 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1092 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1093 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1094 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1095 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1096 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1097 NTCREATEX_SHARE_ACCESS_WRITE|
1098 NTCREATEX_SHARE_ACCESS_DELETE;
1099 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1100 status = smb_raw_open(cli1->tree, tctx, &io);
1101 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1102 fnum = io.ntcreatex.out.file.fnum;
1103 CHECK_VAL(break_info.count, 0);
1104 CHECK_VAL(break_info.failures, 0);
1105 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1108 sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1109 sfi.generic.in.file.path = fname;
1110 sfi.allocation_info.in.alloc_size = 65536 * 8;
1112 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1114 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1115 CHECK_VAL(break_info.count, 1);
1116 CHECK_VAL(break_info.failures, 0);
1117 CHECK_VAL(break_info.level, 0);
1119 smbcli_close(cli1->tree, fnum);
1120 smbcli_close(cli2->tree, fnum2);
1123 smb_raw_exit(cli1->session);
1124 smb_raw_exit(cli2->session);
1125 smbcli_deltree(cli1->tree, BASEDIR);
1129 static bool test_raw_oplock_batch13(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1131 const char *fname = BASEDIR "\\test_batch13.dat";
1135 uint16_t fnum=0, fnum2=0;
1137 if (!torture_setup_dir(cli1, BASEDIR)) {
1142 smbcli_unlink(cli1->tree, fname);
1144 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1145 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli1->tree);
1148 base ntcreatex parms
1150 io.generic.level = RAW_OPEN_NTCREATEX;
1151 io.ntcreatex.in.root_fid = 0;
1152 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1153 io.ntcreatex.in.alloc_size = 0;
1154 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1155 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1156 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1157 io.ntcreatex.in.create_options = 0;
1158 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1159 io.ntcreatex.in.security_flags = 0;
1160 io.ntcreatex.in.fname = fname;
1162 torture_comment(tctx, "open with batch oplock\n");
1163 ZERO_STRUCT(break_info);
1164 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1167 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1168 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1169 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1170 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1171 NTCREATEX_SHARE_ACCESS_WRITE|
1172 NTCREATEX_SHARE_ACCESS_DELETE;
1173 status = smb_raw_open(cli1->tree, tctx, &io);
1174 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1175 fnum = io.ntcreatex.out.file.fnum;
1176 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1178 ZERO_STRUCT(break_info);
1180 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1182 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1183 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1184 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1185 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1186 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1187 NTCREATEX_SHARE_ACCESS_WRITE|
1188 NTCREATEX_SHARE_ACCESS_DELETE;
1189 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1190 status = smb_raw_open(cli2->tree, tctx, &io);
1191 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1192 fnum2 = io.ntcreatex.out.file.fnum;
1193 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1194 CHECK_VAL(break_info.count, 1);
1195 CHECK_VAL(break_info.failures, 0);
1197 smbcli_close(cli1->tree, fnum);
1198 smbcli_close(cli2->tree, fnum2);
1201 smb_raw_exit(cli1->session);
1202 smb_raw_exit(cli2->session);
1203 smbcli_deltree(cli1->tree, BASEDIR);
1207 static bool test_raw_oplock_batch14(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1209 const char *fname = BASEDIR "\\test_batch14.dat";
1213 uint16_t fnum=0, fnum2=0;
1215 if (!torture_setup_dir(cli1, BASEDIR)) {
1220 smbcli_unlink(cli1->tree, fname);
1222 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1225 base ntcreatex parms
1227 io.generic.level = RAW_OPEN_NTCREATEX;
1228 io.ntcreatex.in.root_fid = 0;
1229 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1230 io.ntcreatex.in.alloc_size = 0;
1231 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1232 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1233 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1234 io.ntcreatex.in.create_options = 0;
1235 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1236 io.ntcreatex.in.security_flags = 0;
1237 io.ntcreatex.in.fname = fname;
1239 torture_comment(tctx, "open with batch oplock\n");
1240 ZERO_STRUCT(break_info);
1241 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1243 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1244 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1245 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1246 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1247 NTCREATEX_SHARE_ACCESS_WRITE|
1248 NTCREATEX_SHARE_ACCESS_DELETE;
1249 status = smb_raw_open(cli1->tree, tctx, &io);
1250 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1251 fnum = io.ntcreatex.out.file.fnum;
1252 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1254 ZERO_STRUCT(break_info);
1256 torture_comment(tctx, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1258 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1259 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1260 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1261 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
1262 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1263 NTCREATEX_SHARE_ACCESS_WRITE|
1264 NTCREATEX_SHARE_ACCESS_DELETE;
1265 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
1266 status = smb_raw_open(cli2->tree, tctx, &io);
1267 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1268 fnum2 = io.ntcreatex.out.file.fnum;
1269 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
1270 CHECK_VAL(break_info.count, 1);
1271 CHECK_VAL(break_info.failures, 0);
1273 smbcli_close(cli1->tree, fnum);
1274 smbcli_close(cli2->tree, fnum2);
1276 smb_raw_exit(cli1->session);
1277 smb_raw_exit(cli2->session);
1278 smbcli_deltree(cli1->tree, BASEDIR);
1283 basic testing of oplocks
1285 struct torture_suite *torture_raw_oplock(void)
1287 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "OPLOCK");
1289 torture_suite_add_2smb_test(suite, "NORMAL", test_raw_oplock_normal);
1290 torture_suite_add_2smb_test(suite, "BATCH1", test_raw_oplock_batch1);
1291 torture_suite_add_2smb_test(suite, "BATCH2", test_raw_oplock_batch2);
1292 torture_suite_add_2smb_test(suite, "BATCH3", test_raw_oplock_batch3);
1293 torture_suite_add_2smb_test(suite, "BATCH4", test_raw_oplock_batch4);
1294 torture_suite_add_2smb_test(suite, "BATCH5", test_raw_oplock_batch5);
1295 torture_suite_add_2smb_test(suite, "BATCH6", test_raw_oplock_batch6);
1296 torture_suite_add_2smb_test(suite, "BATCH7", test_raw_oplock_batch7);
1297 torture_suite_add_2smb_test(suite, "BATCH8", test_raw_oplock_batch8);
1298 torture_suite_add_2smb_test(suite, "BATCH9", test_raw_oplock_batch9);
1299 torture_suite_add_2smb_test(suite, "BATCH10", test_raw_oplock_batch10);
1300 torture_suite_add_2smb_test(suite, "BATCH11", test_raw_oplock_batch11);
1301 torture_suite_add_2smb_test(suite, "BATCH12", test_raw_oplock_batch12);
1302 torture_suite_add_2smb_test(suite, "BATCH13", test_raw_oplock_batch13);
1303 torture_suite_add_2smb_test(suite, "BATCH14", test_raw_oplock_batch14);
1309 stress testing of oplocks
1311 BOOL torture_bench_oplock(struct torture_context *torture)
1313 struct smbcli_state **cli;
1315 TALLOC_CTX *mem_ctx = talloc_new(torture);
1316 int torture_nprocs = lp_parm_int(-1, "torture", "nprocs", 4);
1318 int timelimit = torture_setting_int(torture, "timelimit", 10);
1321 struct event_context *ev = event_context_find(mem_ctx);
1323 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
1325 torture_comment(torture, "Opening %d connections\n", torture_nprocs);
1326 for (i=0;i<torture_nprocs;i++) {
1327 if (!torture_open_connection_ev(&cli[i], i, ev)) {
1330 talloc_steal(mem_ctx, cli[i]);
1331 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
1335 if (!torture_setup_dir(cli[0], BASEDIR)) {
1340 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
1341 io.ntcreatex.in.root_fid = 0;
1342 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1343 io.ntcreatex.in.alloc_size = 0;
1344 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1345 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1346 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1347 io.ntcreatex.in.create_options = 0;
1348 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1349 io.ntcreatex.in.security_flags = 0;
1350 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
1351 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1352 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1353 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1355 tv = timeval_current();
1358 we open the same file with SHARE_ACCESS_NONE from all the
1359 connections in a round robin fashion. Each open causes an
1360 oplock break on the previous connection, which is answered
1361 by the oplock_handler_close() to close the file.
1363 This measures how fast we can pass on oplocks, and stresses
1364 the oplock handling code
1366 torture_comment(torture, "Running for %d seconds\n", timelimit);
1367 while (timeval_elapsed(&tv) < timelimit) {
1368 for (i=0;i<torture_nprocs;i++) {
1371 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
1372 CHECK_STATUS(torture, status, NT_STATUS_OK);
1376 if (torture_setting_bool(torture, "progress", true)) {
1377 torture_comment(torture, "%.2f ops/second\r", count/timeval_elapsed(&tv));
1381 torture_comment(torture, "%.2f ops/second\n", count/timeval_elapsed(&tv));
1383 smb_raw_exit(cli[torture_nprocs-1]->session);
1386 smb_raw_exit(cli[0]->session);
1387 smbcli_deltree(cli[0]->tree, BASEDIR);
1388 talloc_free(mem_ctx);