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_comment(tctx, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
31 __location__, #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,
57 uint16_t tid, uint16_t fnum,
58 uint8_t level, void *private)
60 struct smbcli_tree *tree = (struct smbcli_tree *)private;
61 break_info.fnum = fnum;
62 break_info.level = level;
65 printf("Acking to level II in oplock handler\n");
67 return smbcli_oplock_ack(tree, fnum, level);
71 a handler function for oplock break requests. Ack it as a break to none
73 static bool oplock_handler_ack_to_none(struct smbcli_transport *transport,
74 uint16_t tid, uint16_t fnum,
75 uint8_t level, void *private)
77 struct smbcli_tree *tree = (struct smbcli_tree *)private;
78 break_info.fnum = fnum;
79 break_info.level = level;
82 printf("Acking to none in oplock handler\n");
84 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
87 static void oplock_handler_close_recv(struct smbcli_request *req)
90 status = smbcli_request_simple_recv(req);
91 if (!NT_STATUS_IS_OK(status)) {
92 printf("close failed in oplock_handler_close\n");
93 break_info.failures++;
98 a handler function for oplock break requests - close the file
100 static bool oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
101 uint16_t fnum, uint8_t level, void *private)
104 struct smbcli_tree *tree = (struct smbcli_tree *)private;
105 struct smbcli_request *req;
107 break_info.fnum = fnum;
108 break_info.level = level;
111 io.close.level = RAW_CLOSE_CLOSE;
112 io.close.in.file.fnum = fnum;
113 io.close.in.write_time = 0;
114 req = smb_raw_close_send(tree, &io);
116 printf("failed to send close in oplock_handler_close\n");
120 req->async.fn = oplock_handler_close_recv;
121 req->async.private = NULL;
126 static bool test_raw_oplock_normal(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
128 const char *fname = BASEDIR "\\test_normal.dat";
132 union smb_unlink unl;
135 if (!torture_setup_dir(cli1, BASEDIR)) {
140 smbcli_unlink(cli1->tree, fname);
142 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
147 io.generic.level = RAW_OPEN_NTCREATEX;
148 io.ntcreatex.in.root_fid = 0;
149 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
150 io.ntcreatex.in.alloc_size = 0;
151 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
152 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
153 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
154 io.ntcreatex.in.create_options = 0;
155 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
156 io.ntcreatex.in.security_flags = 0;
157 io.ntcreatex.in.fname = fname;
159 torture_comment(tctx, "open a file with a normal oplock\n");
160 ZERO_STRUCT(break_info);
161 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
163 status = smb_raw_open(cli1->tree, tctx, &io);
164 CHECK_STATUS(tctx, status, NT_STATUS_OK);
165 fnum = io.ntcreatex.out.file.fnum;
166 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
168 torture_comment(tctx, "a 2nd open should not cause a break\n");
169 status = smb_raw_open(cli2->tree, tctx, &io);
170 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
171 CHECK_VAL(break_info.count, 0);
172 CHECK_VAL(break_info.failures, 0);
174 torture_comment(tctx, "unlink it - should also be no break\n");
175 unl.unlink.in.pattern = fname;
176 unl.unlink.in.attrib = 0;
177 status = smb_raw_unlink(cli2->tree, &unl);
178 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
179 CHECK_VAL(break_info.count, 0);
180 CHECK_VAL(break_info.failures, 0);
182 smbcli_close(cli1->tree, fnum);
185 smb_raw_exit(cli1->session);
186 smb_raw_exit(cli2->session);
187 smbcli_deltree(cli1->tree, BASEDIR);
191 static bool test_raw_oplock_batch1(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
193 const char *fname = BASEDIR "\\test_batch1.dat";
197 union smb_unlink unl;
201 if (!torture_setup_dir(cli1, BASEDIR)) {
206 smbcli_unlink(cli1->tree, fname);
208 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
213 io.generic.level = RAW_OPEN_NTCREATEX;
214 io.ntcreatex.in.root_fid = 0;
215 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
216 io.ntcreatex.in.alloc_size = 0;
217 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
218 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
219 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
220 io.ntcreatex.in.create_options = 0;
221 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
222 io.ntcreatex.in.security_flags = 0;
223 io.ntcreatex.in.fname = fname;
226 with a batch oplock we get a break
228 torture_comment(tctx, "open with batch oplock\n");
229 ZERO_STRUCT(break_info);
230 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
231 NTCREATEX_FLAGS_REQUEST_OPLOCK |
232 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
233 status = smb_raw_open(cli1->tree, tctx, &io);
234 CHECK_STATUS(tctx, status, NT_STATUS_OK);
235 fnum = io.ntcreatex.out.file.fnum;
236 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
238 torture_comment(tctx, "unlink should generate a break\n");
239 unl.unlink.in.pattern = fname;
240 unl.unlink.in.attrib = 0;
241 status = smb_raw_unlink(cli2->tree, &unl);
242 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
244 CHECK_VAL(break_info.count, 1);
245 CHECK_VAL(break_info.fnum, fnum);
246 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
247 CHECK_VAL(break_info.failures, 0);
249 torture_comment(tctx, "2nd unlink should not generate a break\n");
250 ZERO_STRUCT(break_info);
251 status = smb_raw_unlink(cli2->tree, &unl);
252 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
254 CHECK_VAL(break_info.count, 0);
256 torture_comment(tctx, "writing should generate a self break to none\n");
257 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
259 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
261 CHECK_VAL(break_info.count, 1);
262 CHECK_VAL(break_info.fnum, fnum);
263 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
264 CHECK_VAL(break_info.failures, 0);
266 smbcli_close(cli1->tree, fnum);
269 smb_raw_exit(cli1->session);
270 smb_raw_exit(cli2->session);
271 smbcli_deltree(cli1->tree, BASEDIR);
275 static bool test_raw_oplock_batch2(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
277 const char *fname = BASEDIR "\\test_batch2.dat";
281 union smb_unlink unl;
285 if (!torture_setup_dir(cli1, BASEDIR)) {
290 smbcli_unlink(cli1->tree, fname);
292 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
297 io.generic.level = RAW_OPEN_NTCREATEX;
298 io.ntcreatex.in.root_fid = 0;
299 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
300 io.ntcreatex.in.alloc_size = 0;
301 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
302 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
303 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
304 io.ntcreatex.in.create_options = 0;
305 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
306 io.ntcreatex.in.security_flags = 0;
307 io.ntcreatex.in.fname = fname;
309 torture_comment(tctx, "open with batch oplock\n");
310 ZERO_STRUCT(break_info);
311 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
312 NTCREATEX_FLAGS_REQUEST_OPLOCK |
313 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
314 status = smb_raw_open(cli1->tree, tctx, &io);
315 CHECK_STATUS(tctx, status, NT_STATUS_OK);
316 fnum = io.ntcreatex.out.file.fnum;
317 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
319 torture_comment(tctx, "unlink should generate a break, which we ack as break to none\n");
320 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_none, cli1->tree);
321 unl.unlink.in.pattern = fname;
322 unl.unlink.in.attrib = 0;
323 status = smb_raw_unlink(cli2->tree, &unl);
324 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
326 CHECK_VAL(break_info.count, 1);
327 CHECK_VAL(break_info.fnum, fnum);
328 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
329 CHECK_VAL(break_info.failures, 0);
331 torture_comment(tctx, "2nd unlink should not generate a break\n");
332 ZERO_STRUCT(break_info);
333 status = smb_raw_unlink(cli2->tree, &unl);
334 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
336 CHECK_VAL(break_info.count, 0);
338 torture_comment(tctx, "writing should not generate a break\n");
339 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
341 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
343 CHECK_VAL(break_info.count, 0);
345 smbcli_close(cli1->tree, fnum);
348 smb_raw_exit(cli1->session);
349 smb_raw_exit(cli2->session);
350 smbcli_deltree(cli1->tree, BASEDIR);
354 static bool test_raw_oplock_batch3(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
356 const char *fname = BASEDIR "\\test_batch3.dat";
360 union smb_unlink unl;
363 if (!torture_setup_dir(cli1, BASEDIR)) {
368 smbcli_unlink(cli1->tree, fname);
370 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
375 io.generic.level = RAW_OPEN_NTCREATEX;
376 io.ntcreatex.in.root_fid = 0;
377 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
378 io.ntcreatex.in.alloc_size = 0;
379 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
380 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
381 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
382 io.ntcreatex.in.create_options = 0;
383 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
384 io.ntcreatex.in.security_flags = 0;
385 io.ntcreatex.in.fname = fname;
387 torture_comment(tctx, "if we close on break then the unlink can succeed\n");
388 ZERO_STRUCT(break_info);
389 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
390 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
391 NTCREATEX_FLAGS_REQUEST_OPLOCK |
392 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
393 status = smb_raw_open(cli1->tree, tctx, &io);
394 CHECK_STATUS(tctx, status, NT_STATUS_OK);
395 fnum = io.ntcreatex.out.file.fnum;
396 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
398 unl.unlink.in.pattern = fname;
399 unl.unlink.in.attrib = 0;
400 ZERO_STRUCT(break_info);
401 status = smb_raw_unlink(cli2->tree, &unl);
402 CHECK_STATUS(tctx, status, NT_STATUS_OK);
404 CHECK_VAL(break_info.count, 1);
405 CHECK_VAL(break_info.fnum, fnum);
406 CHECK_VAL(break_info.level, 1);
407 CHECK_VAL(break_info.failures, 0);
409 smbcli_close(cli1->tree, fnum);
412 smb_raw_exit(cli1->session);
413 smb_raw_exit(cli2->session);
414 smbcli_deltree(cli1->tree, BASEDIR);
418 static bool test_raw_oplock_batch4(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
420 const char *fname = BASEDIR "\\test_batch4.dat";
427 if (!torture_setup_dir(cli1, BASEDIR)) {
432 smbcli_unlink(cli1->tree, fname);
434 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
439 io.generic.level = RAW_OPEN_NTCREATEX;
440 io.ntcreatex.in.root_fid = 0;
441 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
442 io.ntcreatex.in.alloc_size = 0;
443 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
444 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
445 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
446 io.ntcreatex.in.create_options = 0;
447 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
448 io.ntcreatex.in.security_flags = 0;
449 io.ntcreatex.in.fname = fname;
451 torture_comment(tctx, "a self read should not cause a break\n");
452 ZERO_STRUCT(break_info);
453 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
455 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
456 NTCREATEX_FLAGS_REQUEST_OPLOCK |
457 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
458 status = smb_raw_open(cli1->tree, tctx, &io);
459 CHECK_STATUS(tctx, status, NT_STATUS_OK);
460 fnum = io.ntcreatex.out.file.fnum;
461 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
463 rd.read.level = RAW_READ_READ;
464 rd.read.in.file.fnum = fnum;
465 rd.read.in.count = 1;
466 rd.read.in.offset = 0;
467 rd.read.in.remaining = 0;
468 status = smb_raw_read(cli1->tree, &rd);
469 CHECK_STATUS(tctx, status, NT_STATUS_OK);
470 CHECK_VAL(break_info.count, 0);
471 CHECK_VAL(break_info.failures, 0);
473 smbcli_close(cli1->tree, fnum);
476 smb_raw_exit(cli1->session);
477 smb_raw_exit(cli2->session);
478 smbcli_deltree(cli1->tree, BASEDIR);
482 static bool test_raw_oplock_batch5(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
484 const char *fname = BASEDIR "\\test_batch5.dat";
490 if (!torture_setup_dir(cli1, BASEDIR)) {
495 smbcli_unlink(cli1->tree, fname);
497 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
502 io.generic.level = RAW_OPEN_NTCREATEX;
503 io.ntcreatex.in.root_fid = 0;
504 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
505 io.ntcreatex.in.alloc_size = 0;
506 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
507 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
508 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
509 io.ntcreatex.in.create_options = 0;
510 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
511 io.ntcreatex.in.security_flags = 0;
512 io.ntcreatex.in.fname = fname;
514 torture_comment(tctx, "a 2nd open should give a break\n");
515 ZERO_STRUCT(break_info);
516 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
518 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
519 NTCREATEX_FLAGS_REQUEST_OPLOCK |
520 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
521 status = smb_raw_open(cli1->tree, tctx, &io);
522 CHECK_STATUS(tctx, status, NT_STATUS_OK);
523 fnum = io.ntcreatex.out.file.fnum;
524 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
526 ZERO_STRUCT(break_info);
528 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
529 status = smb_raw_open(cli2->tree, tctx, &io);
530 CHECK_STATUS(tctx, status, NT_STATUS_SHARING_VIOLATION);
532 CHECK_VAL(break_info.count, 1);
533 CHECK_VAL(break_info.fnum, fnum);
534 CHECK_VAL(break_info.level, 1);
535 CHECK_VAL(break_info.failures, 0);
537 smbcli_close(cli1->tree, fnum);
540 smb_raw_exit(cli1->session);
541 smb_raw_exit(cli2->session);
542 smbcli_deltree(cli1->tree, BASEDIR);
546 static bool test_raw_oplock_batch6(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
548 const char *fname = BASEDIR "\\test_batch6.dat";
552 uint16_t fnum=0, fnum2=0;
555 if (!torture_setup_dir(cli1, BASEDIR)) {
560 smbcli_unlink(cli1->tree, fname);
562 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
567 io.generic.level = RAW_OPEN_NTCREATEX;
568 io.ntcreatex.in.root_fid = 0;
569 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
570 io.ntcreatex.in.alloc_size = 0;
571 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
572 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
573 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
574 io.ntcreatex.in.create_options = 0;
575 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
576 io.ntcreatex.in.security_flags = 0;
577 io.ntcreatex.in.fname = fname;
579 torture_comment(tctx, "a 2nd open should give a break to level II if the first open allowed shared read\n");
580 ZERO_STRUCT(break_info);
581 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
582 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli2->tree);
584 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
585 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
586 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
587 NTCREATEX_FLAGS_REQUEST_OPLOCK |
588 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
589 status = smb_raw_open(cli1->tree, tctx, &io);
590 CHECK_STATUS(tctx, status, NT_STATUS_OK);
591 fnum = io.ntcreatex.out.file.fnum;
592 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
594 ZERO_STRUCT(break_info);
596 status = smb_raw_open(cli2->tree, tctx, &io);
597 CHECK_STATUS(tctx, status, NT_STATUS_OK);
598 fnum2 = io.ntcreatex.out.file.fnum;
599 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
601 CHECK_VAL(break_info.count, 1);
602 CHECK_VAL(break_info.fnum, fnum);
603 CHECK_VAL(break_info.level, 1);
604 CHECK_VAL(break_info.failures, 0);
605 ZERO_STRUCT(break_info);
607 torture_comment(tctx, "write should trigger a break to none on both\n");
608 smbcli_write(cli1->tree, fnum, 0, &c, 0, 1);
610 smbcli_write(cli1->tree, fnum, 0, &c, 1, 1);
612 CHECK_VAL(break_info.count, 2);
613 CHECK_VAL(break_info.level, 0);
614 CHECK_VAL(break_info.failures, 0);
616 smbcli_close(cli1->tree, fnum);
617 smbcli_close(cli2->tree, fnum2);
621 smb_raw_exit(cli1->session);
622 smb_raw_exit(cli2->session);
623 smbcli_deltree(cli1->tree, BASEDIR);
627 static bool test_raw_oplock_batch7(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
629 const char *fname = BASEDIR "\\test_batch7.dat";
633 uint16_t fnum=0, fnum2=0;
635 if (!torture_setup_dir(cli1, BASEDIR)) {
640 smbcli_unlink(cli1->tree, fname);
642 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
647 io.generic.level = RAW_OPEN_NTCREATEX;
648 io.ntcreatex.in.root_fid = 0;
649 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
650 io.ntcreatex.in.alloc_size = 0;
651 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
652 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
653 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
654 io.ntcreatex.in.create_options = 0;
655 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
656 io.ntcreatex.in.security_flags = 0;
657 io.ntcreatex.in.fname = fname;
659 torture_comment(tctx, "a 2nd open should get an oplock when we close instead of ack\n");
660 ZERO_STRUCT(break_info);
661 smbcli_oplock_handler(cli1->transport, oplock_handler_close, cli1->tree);
663 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
664 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
665 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
666 NTCREATEX_FLAGS_REQUEST_OPLOCK |
667 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
668 status = smb_raw_open(cli1->tree, tctx, &io);
669 CHECK_STATUS(tctx, status, NT_STATUS_OK);
670 fnum2 = io.ntcreatex.out.file.fnum;
671 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
673 ZERO_STRUCT(break_info);
675 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
676 NTCREATEX_FLAGS_REQUEST_OPLOCK |
677 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
678 status = smb_raw_open(cli2->tree, tctx, &io);
679 CHECK_STATUS(tctx, status, NT_STATUS_OK);
680 fnum = io.ntcreatex.out.file.fnum;
681 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
683 CHECK_VAL(break_info.count, 1);
684 CHECK_VAL(break_info.fnum, fnum2);
685 CHECK_VAL(break_info.level, 1);
686 CHECK_VAL(break_info.failures, 0);
688 smbcli_close(cli2->tree, fnum);
691 smb_raw_exit(cli1->session);
692 smb_raw_exit(cli2->session);
693 smbcli_deltree(cli1->tree, BASEDIR);
697 static bool test_raw_oplock_batch8(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
699 const char *fname = BASEDIR "\\test_batch8.dat";
703 uint16_t fnum=0, fnum2=0;
705 if (!torture_setup_dir(cli1, BASEDIR)) {
710 smbcli_unlink(cli1->tree, fname);
712 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
717 io.generic.level = RAW_OPEN_NTCREATEX;
718 io.ntcreatex.in.root_fid = 0;
719 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
720 io.ntcreatex.in.alloc_size = 0;
721 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
722 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
723 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
724 io.ntcreatex.in.create_options = 0;
725 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
726 io.ntcreatex.in.security_flags = 0;
727 io.ntcreatex.in.fname = fname;
729 torture_comment(tctx, "open with batch oplock\n");
730 ZERO_STRUCT(break_info);
731 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
733 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
734 NTCREATEX_FLAGS_REQUEST_OPLOCK |
735 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
736 status = smb_raw_open(cli1->tree, tctx, &io);
737 CHECK_STATUS(tctx, status, NT_STATUS_OK);
738 fnum = io.ntcreatex.out.file.fnum;
739 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
741 ZERO_STRUCT(break_info);
742 torture_comment(tctx, "second open with attributes only shouldn't cause oplock break\n");
744 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
745 NTCREATEX_FLAGS_REQUEST_OPLOCK |
746 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
747 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
748 status = smb_raw_open(cli2->tree, tctx, &io);
749 CHECK_STATUS(tctx, status, NT_STATUS_OK);
750 fnum2 = io.ntcreatex.out.file.fnum;
751 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
752 CHECK_VAL(break_info.count, 0);
753 CHECK_VAL(break_info.failures, 0);
755 smbcli_close(cli1->tree, fnum);
756 smbcli_close(cli2->tree, fnum2);
759 smb_raw_exit(cli1->session);
760 smb_raw_exit(cli2->session);
761 smbcli_deltree(cli1->tree, BASEDIR);
765 static bool test_raw_oplock_batch9(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
767 const char *fname = BASEDIR "\\test_batch9.dat";
771 uint16_t fnum=0, fnum2=0;
774 if (!torture_setup_dir(cli1, BASEDIR)) {
779 smbcli_unlink(cli1->tree, fname);
781 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
786 io.generic.level = RAW_OPEN_NTCREATEX;
787 io.ntcreatex.in.root_fid = 0;
788 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
789 io.ntcreatex.in.alloc_size = 0;
790 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
791 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
792 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
793 io.ntcreatex.in.create_options = 0;
794 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
795 io.ntcreatex.in.security_flags = 0;
796 io.ntcreatex.in.fname = fname;
798 torture_comment(tctx, "open with attributes only can create file\n");
800 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
801 NTCREATEX_FLAGS_REQUEST_OPLOCK |
802 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
803 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
804 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
805 status = smb_raw_open(cli1->tree, tctx, &io);
806 CHECK_STATUS(tctx, status, NT_STATUS_OK);
807 fnum = io.ntcreatex.out.file.fnum;
808 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
810 torture_comment(tctx, "Subsequent normal open should break oplock on attribute only open to level II\n");
812 ZERO_STRUCT(break_info);
813 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
815 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
816 NTCREATEX_FLAGS_REQUEST_OPLOCK |
817 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
818 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
819 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
820 status = smb_raw_open(cli2->tree, tctx, &io);
821 CHECK_STATUS(tctx, status, NT_STATUS_OK);
822 fnum2 = io.ntcreatex.out.file.fnum;
823 CHECK_VAL(break_info.count, 1);
824 CHECK_VAL(break_info.fnum, fnum);
825 CHECK_VAL(break_info.failures, 0);
826 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
827 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
828 smbcli_close(cli2->tree, fnum2);
830 torture_comment(tctx, "third oplocked open should grant level2 without break\n");
831 ZERO_STRUCT(break_info);
832 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
833 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli2->tree);
834 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
835 NTCREATEX_FLAGS_REQUEST_OPLOCK |
836 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
837 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
838 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
839 status = smb_raw_open(cli2->tree, tctx, &io);
840 CHECK_STATUS(tctx, status, NT_STATUS_OK);
841 fnum2 = io.ntcreatex.out.file.fnum;
842 CHECK_VAL(break_info.count, 0);
843 CHECK_VAL(break_info.failures, 0);
844 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
846 ZERO_STRUCT(break_info);
848 torture_comment(tctx, "write should trigger a break to none on both\n");
849 smbcli_write(cli2->tree, fnum2, 0, &c, 0, 1);
851 /* Now the oplock break request comes in. But right now we can't
852 * answer it. Do another write */
855 smbcli_write(cli2->tree, fnum2, 0, &c, 1, 1);
857 CHECK_VAL(break_info.count, 2);
858 CHECK_VAL(break_info.level, 0);
859 CHECK_VAL(break_info.failures, 0);
861 smbcli_close(cli1->tree, fnum);
862 smbcli_close(cli2->tree, fnum2);
865 smb_raw_exit(cli1->session);
866 smb_raw_exit(cli2->session);
867 smbcli_deltree(cli1->tree, BASEDIR);
871 static bool test_raw_oplock_batch10(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
873 const char *fname = BASEDIR "\\test_batch10.dat";
877 uint16_t fnum=0, fnum2=0;
879 if (!torture_setup_dir(cli1, BASEDIR)) {
884 smbcli_unlink(cli1->tree, fname);
886 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
891 io.generic.level = RAW_OPEN_NTCREATEX;
892 io.ntcreatex.in.root_fid = 0;
893 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
894 io.ntcreatex.in.alloc_size = 0;
895 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
896 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
897 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
898 io.ntcreatex.in.create_options = 0;
899 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
900 io.ntcreatex.in.security_flags = 0;
901 io.ntcreatex.in.fname = fname;
903 torture_comment(tctx, "Open with oplock after a non-oplock open should grant level2\n");
904 ZERO_STRUCT(break_info);
905 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
906 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
907 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
908 NTCREATEX_SHARE_ACCESS_WRITE|
909 NTCREATEX_SHARE_ACCESS_DELETE;
910 status = smb_raw_open(cli1->tree, tctx, &io);
911 CHECK_STATUS(tctx, status, NT_STATUS_OK);
912 fnum = io.ntcreatex.out.file.fnum;
913 CHECK_VAL(break_info.count, 0);
914 CHECK_VAL(break_info.failures, 0);
915 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
917 smbcli_oplock_handler(cli2->transport, oplock_handler_ack_to_levelII, cli2->tree);
919 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
920 NTCREATEX_FLAGS_REQUEST_OPLOCK |
921 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
922 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
923 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
924 NTCREATEX_SHARE_ACCESS_WRITE|
925 NTCREATEX_SHARE_ACCESS_DELETE;
926 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
927 status = smb_raw_open(cli2->tree, tctx, &io);
928 CHECK_STATUS(tctx, status, NT_STATUS_OK);
929 fnum2 = io.ntcreatex.out.file.fnum;
930 CHECK_VAL(break_info.count, 0);
931 CHECK_VAL(break_info.failures, 0);
932 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
934 torture_comment(tctx, "write should trigger a break to none\n");
937 wr.write.level = RAW_WRITE_WRITE;
938 wr.write.in.file.fnum = fnum;
939 wr.write.in.count = 1;
940 wr.write.in.offset = 0;
941 wr.write.in.remaining = 0;
942 wr.write.in.data = (const uint8_t *)"x";
943 status = smb_raw_write(cli1->tree, &wr);
944 CHECK_STATUS(tctx, status, NT_STATUS_OK);
947 /* Now the oplock break request comes in. But right now we can't
948 * answer it. Do another write */
954 wr.write.level = RAW_WRITE_WRITE;
955 wr.write.in.file.fnum = fnum;
956 wr.write.in.count = 1;
957 wr.write.in.offset = 0;
958 wr.write.in.remaining = 0;
959 wr.write.in.data = (const uint8_t *)"x";
960 status = smb_raw_write(cli1->tree, &wr);
961 CHECK_STATUS(tctx, status, NT_STATUS_OK);
964 CHECK_VAL(break_info.count, 1);
965 CHECK_VAL(break_info.fnum, fnum2);
966 CHECK_VAL(break_info.level, 0);
967 CHECK_VAL(break_info.failures, 0);
969 smbcli_close(cli1->tree, fnum);
970 smbcli_close(cli2->tree, fnum2);
973 smb_raw_exit(cli1->session);
974 smb_raw_exit(cli2->session);
975 smbcli_deltree(cli1->tree, BASEDIR);
979 static bool test_raw_oplock_batch11(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
981 const char *fname = BASEDIR "\\test_batch11.dat";
985 union smb_setfileinfo sfi;
988 if (!torture_setup_dir(cli1, BASEDIR)) {
993 smbcli_unlink(cli1->tree, fname);
995 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1000 io.generic.level = RAW_OPEN_NTCREATEX;
1001 io.ntcreatex.in.root_fid = 0;
1002 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1003 io.ntcreatex.in.alloc_size = 0;
1004 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1005 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1006 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1007 io.ntcreatex.in.create_options = 0;
1008 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1009 io.ntcreatex.in.security_flags = 0;
1010 io.ntcreatex.in.fname = fname;
1012 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1013 torture_comment(tctx, "Test if setpathinfo set EOF breaks oplocks.\n");
1015 ZERO_STRUCT(break_info);
1016 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1018 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1019 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1020 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1021 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1022 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1023 NTCREATEX_SHARE_ACCESS_WRITE|
1024 NTCREATEX_SHARE_ACCESS_DELETE;
1025 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1026 status = smb_raw_open(cli1->tree, tctx, &io);
1027 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1028 fnum = io.ntcreatex.out.file.fnum;
1029 CHECK_VAL(break_info.count, 0);
1030 CHECK_VAL(break_info.failures, 0);
1031 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1034 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
1035 sfi.generic.in.file.path = fname;
1036 sfi.end_of_file_info.in.size = 100;
1038 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1040 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1041 CHECK_VAL(break_info.count, 1);
1042 CHECK_VAL(break_info.failures, 0);
1043 CHECK_VAL(break_info.level, 0);
1045 smbcli_close(cli1->tree, fnum);
1048 smb_raw_exit(cli1->session);
1049 smb_raw_exit(cli2->session);
1050 smbcli_deltree(cli1->tree, BASEDIR);
1054 static bool test_raw_oplock_batch12(struct torture_context *tctx, struct smbcli_state *cli1, struct smbcli_state *cli2)
1056 const char *fname = BASEDIR "\\test_batch12.dat";
1060 union smb_setfileinfo sfi;
1063 if (!torture_setup_dir(cli1, BASEDIR)) {
1068 smbcli_unlink(cli1->tree, fname);
1070 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1073 base ntcreatex parms
1075 io.generic.level = RAW_OPEN_NTCREATEX;
1076 io.ntcreatex.in.root_fid = 0;
1077 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1078 io.ntcreatex.in.alloc_size = 0;
1079 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1080 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1081 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1082 io.ntcreatex.in.create_options = 0;
1083 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1084 io.ntcreatex.in.security_flags = 0;
1085 io.ntcreatex.in.fname = fname;
1087 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1088 torture_comment(tctx, "Test if setpathinfo allocation size breaks oplocks.\n");
1090 ZERO_STRUCT(break_info);
1091 smbcli_oplock_handler(cli1->transport, oplock_handler_ack_to_levelII, cli1->tree);
1093 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1094 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1095 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1096 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1097 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1098 NTCREATEX_SHARE_ACCESS_WRITE|
1099 NTCREATEX_SHARE_ACCESS_DELETE;
1100 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1101 status = smb_raw_open(cli1->tree, tctx, &io);
1102 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1103 fnum = io.ntcreatex.out.file.fnum;
1104 CHECK_VAL(break_info.count, 0);
1105 CHECK_VAL(break_info.failures, 0);
1106 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
1109 sfi.generic.level = SMB_SFILEINFO_ALLOCATION_INFORMATION;
1110 sfi.generic.in.file.path = fname;
1111 sfi.allocation_info.in.alloc_size = 65536 * 8;
1113 status = smb_raw_setpathinfo(cli2->tree, &sfi);
1115 CHECK_STATUS(tctx, status, NT_STATUS_OK);
1116 CHECK_VAL(break_info.count, 1);
1117 CHECK_VAL(break_info.failures, 0);
1118 CHECK_VAL(break_info.level, 0);
1120 smbcli_close(cli1->tree, fnum);
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(TALLOC_CTX *mem_ctx)
1287 struct torture_suite *suite = torture_suite_create(mem_ctx, "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 = torture_setting_int(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, torture, 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);
1393 static struct hold_oplock_info {
1395 bool close_on_break;
1396 uint32_t share_access;
1399 { BASEDIR "\\notshared_close", true,
1400 NTCREATEX_SHARE_ACCESS_NONE, },
1401 { BASEDIR "\\notshared_noclose", false,
1402 NTCREATEX_SHARE_ACCESS_NONE, },
1403 { BASEDIR "\\shared_close", true,
1404 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
1405 { BASEDIR "\\shared_noclose", false,
1406 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
1409 static bool oplock_handler_hold(struct smbcli_transport *transport,
1410 uint16_t tid, uint16_t fnum, uint8_t level,
1413 struct smbcli_tree *tree = (struct smbcli_tree *)private;
1414 struct hold_oplock_info *info;
1417 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
1418 if (hold_info[i].fnum == fnum) break;
1421 if (i == ARRAY_SIZE(hold_info)) {
1422 printf("oplock break for unknown fnum %u\n", fnum);
1426 info = &hold_info[i];
1428 if (info->close_on_break) {
1429 printf("oplock break on %s - closing\n",
1431 oplock_handler_close(transport, tid, fnum, level, private);
1435 printf("oplock break on %s - acking break\n", info->fname);
1437 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
1442 used for manual testing of oplocks - especially interaction with
1443 other filesystems (such as NFS and local access)
1445 bool torture_hold_oplock(struct torture_context *torture,
1446 struct smbcli_state *cli)
1448 struct event_context *ev =
1449 (struct event_context *)cli->transport->socket->event.ctx;
1452 printf("Setting up open files with oplocks in %s\n", BASEDIR);
1454 if (!torture_setup_dir(cli, BASEDIR)) {
1458 smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
1460 /* setup the files */
1461 for (i=0;i<ARRAY_SIZE(hold_info);i++) {
1466 io.generic.level = RAW_OPEN_NTCREATEX;
1467 io.ntcreatex.in.root_fid = 0;
1468 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1469 io.ntcreatex.in.alloc_size = 0;
1470 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1471 io.ntcreatex.in.share_access = hold_info[i].share_access;
1472 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1473 io.ntcreatex.in.create_options = 0;
1474 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1475 io.ntcreatex.in.security_flags = 0;
1476 io.ntcreatex.in.fname = hold_info[i].fname;
1477 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
1478 NTCREATEX_FLAGS_REQUEST_OPLOCK |
1479 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
1480 printf("opening %s\n", hold_info[i].fname);
1482 status = smb_raw_open(cli->tree, cli, &io);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 printf("Failed to open %s - %s\n",
1485 hold_info[i].fname, nt_errstr(status));
1489 if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
1490 printf("Oplock not granted for %s - expected %d but got %d\n",
1491 hold_info[i].fname, BATCH_OPLOCK_RETURN,
1492 io.ntcreatex.out.oplock_level);
1495 hold_info[i].fnum = io.ntcreatex.out.file.fnum;
1497 /* make the file non-zero size */
1498 if (smbcli_write(cli->tree, hold_info[i].fnum, 0, &c, 0, 1) != 1) {
1499 printf("Failed to write to file\n");
1504 printf("Waiting for oplock events\n");
1505 event_loop_wait(ev);