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 "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "libcli/libcli.h"
24 #include "torture/util.h"
25 #include "lib/events/events.h"
26 #include "param/param.h"
27 #include "lib/cmdline/popt_common.h"
28 #include "libcli/resolve/resolve.h"
30 #define CHECK_VAL(v, correct) do { \
31 if ((v) != (correct)) { \
32 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
33 __location__, #v, (int)v, (int)correct); \
37 #define CHECK_RANGE(v, min, max) do { \
38 if ((v) < (min) || (v) > (max)) { \
39 torture_warning(tctx, "(%s): wrong value for %s got " \
40 "%d - should be between %d and %d\n", \
41 __location__, #v, (int)v, (int)min, (int)max); \
44 #define CHECK_STRMATCH(v, correct) do { \
45 if (!v || strstr((v),(correct)) == NULL) { \
46 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
47 __location__, #v, v?v:"NULL", correct); \
52 #define CHECK_STATUS(tctx, status, correct) do { \
53 if (!NT_STATUS_EQUAL(status, correct)) { \
54 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
55 nt_errstr(status), nt_errstr(correct)); \
68 #define BASEDIR "\\test_oplock"
71 a handler function for oplock break requests. Ack it as a break to level II if possible
73 static bool oplock_handler_ack_to_given(struct smbcli_transport
*transport
,
74 uint16_t tid
, uint16_t fnum
,
75 uint8_t level
, void *private_data
)
77 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
80 break_info
.fnum
= fnum
;
81 break_info
.level
= level
;
85 case OPLOCK_BREAK_TO_LEVEL_II
:
88 case OPLOCK_BREAK_TO_NONE
:
93 break_info
.failures
++;
95 printf("Acking to %s [0x%02X] in oplock handler\n",
98 return smbcli_oplock_ack(tree
, fnum
, level
);
102 a handler function for oplock break requests. Ack it as a break to none
104 static bool oplock_handler_ack_to_none(struct smbcli_transport
*transport
,
105 uint16_t tid
, uint16_t fnum
,
106 uint8_t level
, void *private_data
)
108 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
109 break_info
.fnum
= fnum
;
110 break_info
.level
= level
;
113 printf("Acking to none in oplock handler\n");
115 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
119 a handler function for oplock break requests. Let it timeout
121 static bool oplock_handler_timeout(struct smbcli_transport
*transport
,
122 uint16_t tid
, uint16_t fnum
,
123 uint8_t level
, void *private_data
)
125 break_info
.fnum
= fnum
;
126 break_info
.level
= level
;
129 printf("Let oplock break timeout\n");
133 static void oplock_handler_close_recv(struct smbcli_request
*req
)
136 status
= smbcli_request_simple_recv(req
);
137 if (!NT_STATUS_IS_OK(status
)) {
138 printf("close failed in oplock_handler_close\n");
139 break_info
.failures
++;
144 a handler function for oplock break requests - close the file
146 static bool oplock_handler_close(struct smbcli_transport
*transport
, uint16_t tid
,
147 uint16_t fnum
, uint8_t level
, void *private_data
)
150 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
151 struct smbcli_request
*req
;
153 break_info
.fnum
= fnum
;
154 break_info
.level
= level
;
157 io
.close
.level
= RAW_CLOSE_CLOSE
;
158 io
.close
.in
.file
.fnum
= fnum
;
159 io
.close
.in
.write_time
= 0;
160 req
= smb_raw_close_send(tree
, &io
);
162 printf("failed to send close in oplock_handler_close\n");
166 req
->async
.fn
= oplock_handler_close_recv
;
167 req
->async
.private_data
= NULL
;
172 static bool open_connection_no_level2_oplocks(struct torture_context
*tctx
,
173 struct smbcli_state
**c
)
176 struct smbcli_options options
;
177 struct smbcli_session_options session_options
;
179 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
180 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
182 options
.use_level2_oplocks
= false;
184 status
= smbcli_full_connection(tctx
, c
,
185 torture_setting_string(tctx
, "host", NULL
),
186 lpcfg_smb_ports(tctx
->lp_ctx
),
187 torture_setting_string(tctx
, "share", NULL
),
188 NULL
, lpcfg_socket_options(tctx
->lp_ctx
), cmdline_credentials
,
189 lpcfg_resolve_context(tctx
->lp_ctx
),
190 tctx
->ev
, &options
, &session_options
,
191 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
192 if (!NT_STATUS_IS_OK(status
)) {
193 torture_comment(tctx
, "Failed to open connection - %s\n",
202 Timer handler function notifies the registering function that time is up
204 static void timeout_cb(struct tevent_context
*ev
,
205 struct tevent_timer
*te
,
206 struct timeval current_time
,
209 bool *timesup
= (bool *)private_data
;
215 Wait a short period of time to receive a single oplock break request
217 static void torture_wait_for_oplock_break(struct torture_context
*tctx
)
219 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
220 struct tevent_timer
*te
= NULL
;
222 bool timesup
= false;
223 int old_count
= break_info
.count
;
225 /* Wait .1 seconds for an oplock break */
226 ne
= tevent_timeval_current_ofs(0, 100000);
228 if ((te
= event_add_timed(tctx
->ev
, tmp_ctx
, ne
, timeout_cb
, ×up
))
231 torture_comment(tctx
, "Failed to wait for an oplock break. "
232 "test results may not be accurate.");
236 while (!timesup
&& break_info
.count
< old_count
+ 1) {
237 if (event_loop_once(tctx
->ev
) != 0) {
238 torture_comment(tctx
, "Failed to wait for an oplock "
239 "break. test results may not be "
246 /* We don't know if the timed event fired and was freed, we received
247 * our oplock break, or some other event triggered the loop. Thus,
248 * we create a tmp_ctx to be able to safely free/remove the timed
249 * event in all 3 cases. */
250 talloc_free(tmp_ctx
);
255 static uint8_t get_break_level1_to_none_count(struct torture_context
*tctx
)
257 return torture_setting_bool(tctx
, "2_step_break_to_none", false) ?
261 static bool test_raw_oplock_exclusive1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
263 const char *fname
= BASEDIR
"\\test_exclusive1.dat";
267 union smb_unlink unl
;
270 if (!torture_setup_dir(cli1
, BASEDIR
)) {
275 smbcli_unlink(cli1
->tree
, fname
);
277 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
282 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
283 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
284 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
285 io
.ntcreatex
.in
.alloc_size
= 0;
286 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
287 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
288 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
289 io
.ntcreatex
.in
.create_options
= 0;
290 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
291 io
.ntcreatex
.in
.security_flags
= 0;
292 io
.ntcreatex
.in
.fname
= fname
;
294 torture_comment(tctx
, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
295 ZERO_STRUCT(break_info
);
296 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
298 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
299 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
300 fnum
= io
.ntcreatex
.out
.file
.fnum
;
301 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
303 torture_comment(tctx
, "a 2nd open should not cause a break\n");
304 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
305 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
306 torture_wait_for_oplock_break(tctx
);
307 CHECK_VAL(break_info
.count
, 0);
308 CHECK_VAL(break_info
.failures
, 0);
310 torture_comment(tctx
, "unlink it - should also be no break\n");
311 unl
.unlink
.in
.pattern
= fname
;
312 unl
.unlink
.in
.attrib
= 0;
313 status
= smb_raw_unlink(cli2
->tree
, &unl
);
314 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
315 torture_wait_for_oplock_break(tctx
);
316 CHECK_VAL(break_info
.count
, 0);
317 CHECK_VAL(break_info
.failures
, 0);
319 smbcli_close(cli1
->tree
, fnum
);
322 smb_raw_exit(cli1
->session
);
323 smb_raw_exit(cli2
->session
);
324 smbcli_deltree(cli1
->tree
, BASEDIR
);
328 static bool test_raw_oplock_exclusive2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
330 const char *fname
= BASEDIR
"\\test_exclusive2.dat";
334 union smb_unlink unl
;
335 uint16_t fnum
=0, fnum2
=0;
337 if (!torture_setup_dir(cli1
, BASEDIR
)) {
342 smbcli_unlink(cli1
->tree
, fname
);
344 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
349 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
350 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
351 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
352 io
.ntcreatex
.in
.alloc_size
= 0;
353 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
354 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
355 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
356 io
.ntcreatex
.in
.create_options
= 0;
357 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
358 io
.ntcreatex
.in
.security_flags
= 0;
359 io
.ntcreatex
.in
.fname
= fname
;
361 torture_comment(tctx
, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
362 ZERO_STRUCT(break_info
);
363 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
364 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
365 NTCREATEX_SHARE_ACCESS_WRITE
|
366 NTCREATEX_SHARE_ACCESS_DELETE
;
368 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
369 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
370 fnum
= io
.ntcreatex
.out
.file
.fnum
;
371 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
373 torture_comment(tctx
, "a 2nd open should cause a break to level 2\n");
374 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
375 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
376 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
377 torture_wait_for_oplock_break(tctx
);
378 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
379 CHECK_VAL(break_info
.count
, 1);
380 CHECK_VAL(break_info
.fnum
, fnum
);
381 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
382 CHECK_VAL(break_info
.failures
, 0);
383 ZERO_STRUCT(break_info
);
385 /* now we have 2 level II oplocks... */
386 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
387 unl
.unlink
.in
.pattern
= fname
;
388 unl
.unlink
.in
.attrib
= 0;
389 status
= smb_raw_unlink(cli2
->tree
, &unl
);
390 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
391 torture_wait_for_oplock_break(tctx
);
392 CHECK_VAL(break_info
.count
, 0);
393 CHECK_VAL(break_info
.failures
, 0);
395 torture_comment(tctx
, "close 1st handle\n");
396 smbcli_close(cli1
->tree
, fnum
);
398 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
399 unl
.unlink
.in
.pattern
= fname
;
400 unl
.unlink
.in
.attrib
= 0;
401 status
= smb_raw_unlink(cli2
->tree
, &unl
);
402 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
403 torture_wait_for_oplock_break(tctx
);
404 CHECK_VAL(break_info
.count
, 0);
405 CHECK_VAL(break_info
.failures
, 0);
407 torture_comment(tctx
, "close 2nd handle\n");
408 smbcli_close(cli2
->tree
, fnum2
);
410 torture_comment(tctx
, "unlink it\n");
411 unl
.unlink
.in
.pattern
= fname
;
412 unl
.unlink
.in
.attrib
= 0;
413 status
= smb_raw_unlink(cli2
->tree
, &unl
);
414 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
415 torture_wait_for_oplock_break(tctx
);
416 CHECK_VAL(break_info
.count
, 0);
417 CHECK_VAL(break_info
.failures
, 0);
420 smb_raw_exit(cli1
->session
);
421 smb_raw_exit(cli2
->session
);
422 smbcli_deltree(cli1
->tree
, BASEDIR
);
426 static bool test_raw_oplock_exclusive3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
428 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
432 union smb_setfileinfo sfi
;
435 if (!torture_setup_dir(cli1
, BASEDIR
)) {
440 smbcli_unlink(cli1
->tree
, fname
);
442 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
447 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
448 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
449 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
450 io
.ntcreatex
.in
.alloc_size
= 0;
451 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
452 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
453 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
454 io
.ntcreatex
.in
.create_options
= 0;
455 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
456 io
.ntcreatex
.in
.security_flags
= 0;
457 io
.ntcreatex
.in
.fname
= fname
;
459 torture_comment(tctx
, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
461 ZERO_STRUCT(break_info
);
462 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
464 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
465 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
466 fnum
= io
.ntcreatex
.out
.file
.fnum
;
467 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
469 torture_comment(tctx
, "setpathinfo EOF should trigger a break to none\n");
471 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
472 sfi
.generic
.in
.file
.path
= fname
;
473 sfi
.end_of_file_info
.in
.size
= 100;
475 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
477 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
478 torture_wait_for_oplock_break(tctx
);
479 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
480 CHECK_VAL(break_info
.failures
, 0);
481 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
483 smbcli_close(cli1
->tree
, fnum
);
486 smb_raw_exit(cli1
->session
);
487 smb_raw_exit(cli2
->session
);
488 smbcli_deltree(cli1
->tree
, BASEDIR
);
492 static bool test_raw_oplock_exclusive4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
494 const char *fname
= BASEDIR
"\\test_exclusive4.dat";
498 uint16_t fnum
=0, fnum2
=0;
500 if (!torture_setup_dir(cli1
, BASEDIR
)) {
505 smbcli_unlink(cli1
->tree
, fname
);
507 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
512 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
513 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
514 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
515 io
.ntcreatex
.in
.alloc_size
= 0;
516 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
517 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
518 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
519 io
.ntcreatex
.in
.create_options
= 0;
520 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
521 io
.ntcreatex
.in
.security_flags
= 0;
522 io
.ntcreatex
.in
.fname
= fname
;
524 torture_comment(tctx
, "EXCLUSIVE4: open with exclusive oplock\n");
525 ZERO_STRUCT(break_info
);
526 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
528 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
529 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
530 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
531 fnum
= io
.ntcreatex
.out
.file
.fnum
;
532 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
534 ZERO_STRUCT(break_info
);
535 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
537 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
538 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
539 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
540 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
541 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
542 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
543 torture_wait_for_oplock_break(tctx
);
544 CHECK_VAL(break_info
.count
, 0);
545 CHECK_VAL(break_info
.failures
, 0);
547 smbcli_close(cli1
->tree
, fnum
);
548 smbcli_close(cli2
->tree
, fnum2
);
551 smb_raw_exit(cli1
->session
);
552 smb_raw_exit(cli2
->session
);
553 smbcli_deltree(cli1
->tree
, BASEDIR
);
557 static bool test_raw_oplock_exclusive5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
559 const char *fname
= BASEDIR
"\\test_exclusive5.dat";
563 uint16_t fnum
=0, fnum2
=0;
565 if (!torture_setup_dir(cli1
, BASEDIR
)) {
570 smbcli_unlink(cli1
->tree
, fname
);
572 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
573 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
578 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
579 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
580 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
581 io
.ntcreatex
.in
.alloc_size
= 0;
582 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
583 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
584 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
585 io
.ntcreatex
.in
.create_options
= 0;
586 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
587 io
.ntcreatex
.in
.security_flags
= 0;
588 io
.ntcreatex
.in
.fname
= fname
;
590 torture_comment(tctx
, "EXCLUSIVE5: open with exclusive oplock\n");
591 ZERO_STRUCT(break_info
);
592 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
595 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
596 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
597 NTCREATEX_SHARE_ACCESS_WRITE
|
598 NTCREATEX_SHARE_ACCESS_DELETE
;
599 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
600 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
601 fnum
= io
.ntcreatex
.out
.file
.fnum
;
602 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
604 ZERO_STRUCT(break_info
);
606 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
608 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
609 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
610 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
611 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
612 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
613 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
614 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
615 torture_wait_for_oplock_break(tctx
);
616 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
617 CHECK_VAL(break_info
.failures
, 0);
619 smbcli_close(cli1
->tree
, fnum
);
620 smbcli_close(cli2
->tree
, fnum2
);
623 smb_raw_exit(cli1
->session
);
624 smb_raw_exit(cli2
->session
);
625 smbcli_deltree(cli1
->tree
, BASEDIR
);
629 static bool test_raw_oplock_exclusive6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
631 const char *fname1
= BASEDIR
"\\test_exclusive6_1.dat";
632 const char *fname2
= BASEDIR
"\\test_exclusive6_2.dat";
639 if (!torture_setup_dir(cli1
, BASEDIR
)) {
644 smbcli_unlink(cli1
->tree
, fname1
);
645 smbcli_unlink(cli1
->tree
, fname2
);
647 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
652 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
653 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
654 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
655 io
.ntcreatex
.in
.alloc_size
= 0;
656 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
657 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
658 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
659 io
.ntcreatex
.in
.create_options
= 0;
660 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
661 io
.ntcreatex
.in
.security_flags
= 0;
662 io
.ntcreatex
.in
.fname
= fname1
;
664 torture_comment(tctx
, "EXCLUSIVE6: open a file with an exclusive "
665 "oplock (share mode: none)\n");
666 ZERO_STRUCT(break_info
);
667 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
669 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
670 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
671 fnum
= io
.ntcreatex
.out
.file
.fnum
;
672 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
674 torture_comment(tctx
, "rename should not generate a break but get a "
675 "sharing violation\n");
677 rn
.generic
.level
= RAW_RENAME_RENAME
;
678 rn
.rename
.in
.pattern1
= fname1
;
679 rn
.rename
.in
.pattern2
= fname2
;
680 rn
.rename
.in
.attrib
= 0;
682 torture_comment(tctx
, "trying rename while first file open\n");
683 status
= smb_raw_rename(cli2
->tree
, &rn
);
685 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
686 torture_wait_for_oplock_break(tctx
);
687 CHECK_VAL(break_info
.count
, 0);
688 CHECK_VAL(break_info
.failures
, 0);
690 smbcli_close(cli1
->tree
, fnum
);
693 smb_raw_exit(cli1
->session
);
694 smb_raw_exit(cli2
->session
);
695 smbcli_deltree(cli1
->tree
, BASEDIR
);
700 * Exclusive version of batch19
702 static bool test_raw_oplock_exclusive7(struct torture_context
*tctx
,
703 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
705 const char *fname1
= BASEDIR
"\\test_exclusiv6_1.dat";
706 const char *fname2
= BASEDIR
"\\test_exclusiv6_2.dat";
707 const char *fname3
= BASEDIR
"\\test_exclusiv6_3.dat";
711 union smb_fileinfo qfi
;
712 union smb_setfileinfo sfi
;
716 if (!torture_setup_dir(cli1
, BASEDIR
)) {
721 smbcli_unlink(cli1
->tree
, fname1
);
722 smbcli_unlink(cli1
->tree
, fname2
);
723 smbcli_unlink(cli1
->tree
, fname3
);
725 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
731 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
732 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
733 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
734 io
.ntcreatex
.in
.alloc_size
= 0;
735 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
736 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
737 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
738 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
739 io
.ntcreatex
.in
.create_options
= 0;
740 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
741 io
.ntcreatex
.in
.security_flags
= 0;
742 io
.ntcreatex
.in
.fname
= fname1
;
744 torture_comment(tctx
, "open a file with an exclusive oplock (share "
746 ZERO_STRUCT(break_info
);
747 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
748 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
749 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
750 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
751 fnum
= io
.ntcreatex
.out
.file
.fnum
;
752 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
754 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
757 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
758 sfi
.generic
.in
.file
.path
= fname1
;
759 sfi
.rename_information
.in
.overwrite
= 0;
760 sfi
.rename_information
.in
.root_fid
= 0;
761 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
763 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
764 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
766 torture_wait_for_oplock_break(tctx
);
767 CHECK_VAL(break_info
.failures
, 0);
769 if (TARGET_IS_WINXP(tctx
)) {
770 /* XP incorrectly breaks to level2. */
771 CHECK_VAL(break_info
.count
, 1);
772 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
774 /* Exclusive oplocks should not be broken on rename. */
775 CHECK_VAL(break_info
.failures
, 0);
776 CHECK_VAL(break_info
.count
, 0);
780 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
781 qfi
.generic
.in
.file
.fnum
= fnum
;
783 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
784 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
785 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
787 /* Try breaking to level2 and then see if rename breaks the level2.*/
788 ZERO_STRUCT(break_info
);
789 io
.ntcreatex
.in
.fname
= fname2
;
790 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
791 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
792 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
793 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
795 torture_wait_for_oplock_break(tctx
);
796 CHECK_VAL(break_info
.failures
, 0);
798 if (TARGET_IS_WINXP(tctx
)) {
799 /* XP already broke to level2. */
800 CHECK_VAL(break_info
.failures
, 0);
801 CHECK_VAL(break_info
.count
, 0);
803 /* Break to level 2 expected. */
804 CHECK_VAL(break_info
.count
, 1);
805 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
808 ZERO_STRUCT(break_info
);
809 sfi
.generic
.in
.file
.path
= fname2
;
810 sfi
.rename_information
.in
.overwrite
= 0;
811 sfi
.rename_information
.in
.root_fid
= 0;
812 sfi
.rename_information
.in
.new_name
= fname1
+strlen(BASEDIR
)+1;
814 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
815 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
817 /* Level2 oplocks are not broken on rename. */
818 torture_wait_for_oplock_break(tctx
);
819 CHECK_VAL(break_info
.failures
, 0);
820 CHECK_VAL(break_info
.count
, 0);
822 /* Close and re-open file with oplock. */
823 smbcli_close(cli1
->tree
, fnum
);
824 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
825 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
826 fnum
= io
.ntcreatex
.out
.file
.fnum
;
827 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
829 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
830 "should not trigger a break nor a violation\n");
831 ZERO_STRUCT(break_info
);
833 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
834 sfi
.generic
.in
.file
.fnum
= fnum
;
835 sfi
.rename_information
.in
.overwrite
= 0;
836 sfi
.rename_information
.in
.root_fid
= 0;
837 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
839 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
840 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
842 torture_wait_for_oplock_break(tctx
);
843 if (TARGET_IS_WINXP(tctx
)) {
844 /* XP incorrectly breaks to level2. */
845 CHECK_VAL(break_info
.count
, 1);
846 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
848 CHECK_VAL(break_info
.count
, 0);
852 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
853 qfi
.generic
.in
.file
.fnum
= fnum
;
855 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
856 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
857 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
860 smbcli_close(cli1
->tree
, fnum
);
861 smbcli_close(cli2
->tree
, fnum2
);
863 smb_raw_exit(cli1
->session
);
864 smb_raw_exit(cli2
->session
);
865 smbcli_deltree(cli1
->tree
, BASEDIR
);
869 static bool test_raw_oplock_batch1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
871 const char *fname
= BASEDIR
"\\test_batch1.dat";
875 union smb_unlink unl
;
879 if (!torture_setup_dir(cli1
, BASEDIR
)) {
884 smbcli_unlink(cli1
->tree
, fname
);
886 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
891 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
892 io
.ntcreatex
.in
.root_fid
.fnum
= 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
;
904 with a batch oplock we get a break
906 torture_comment(tctx
, "BATCH1: open with batch oplock\n");
907 ZERO_STRUCT(break_info
);
908 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
909 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
910 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
911 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
912 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
913 fnum
= io
.ntcreatex
.out
.file
.fnum
;
914 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
916 torture_comment(tctx
, "unlink should generate a break\n");
917 unl
.unlink
.in
.pattern
= fname
;
918 unl
.unlink
.in
.attrib
= 0;
919 status
= smb_raw_unlink(cli2
->tree
, &unl
);
920 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
922 torture_wait_for_oplock_break(tctx
);
923 CHECK_VAL(break_info
.count
, 1);
924 CHECK_VAL(break_info
.fnum
, fnum
);
925 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
926 CHECK_VAL(break_info
.failures
, 0);
928 torture_comment(tctx
, "2nd unlink should not generate a break\n");
929 ZERO_STRUCT(break_info
);
930 status
= smb_raw_unlink(cli2
->tree
, &unl
);
931 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
933 torture_wait_for_oplock_break(tctx
);
934 CHECK_VAL(break_info
.count
, 0);
936 torture_comment(tctx
, "writing should generate a self break to none\n");
937 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
939 torture_wait_for_oplock_break(tctx
);
940 torture_wait_for_oplock_break(tctx
);
941 CHECK_VAL(break_info
.count
, 1);
942 CHECK_VAL(break_info
.fnum
, fnum
);
943 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
944 CHECK_VAL(break_info
.failures
, 0);
946 smbcli_close(cli1
->tree
, fnum
);
949 smb_raw_exit(cli1
->session
);
950 smb_raw_exit(cli2
->session
);
951 smbcli_deltree(cli1
->tree
, BASEDIR
);
955 static bool test_raw_oplock_batch2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
957 const char *fname
= BASEDIR
"\\test_batch2.dat";
961 union smb_unlink unl
;
965 if (!torture_setup_dir(cli1
, BASEDIR
)) {
970 smbcli_unlink(cli1
->tree
, fname
);
972 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
977 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
978 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
979 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
980 io
.ntcreatex
.in
.alloc_size
= 0;
981 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
982 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
983 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
984 io
.ntcreatex
.in
.create_options
= 0;
985 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
986 io
.ntcreatex
.in
.security_flags
= 0;
987 io
.ntcreatex
.in
.fname
= fname
;
989 torture_comment(tctx
, "BATCH2: open with batch oplock\n");
990 ZERO_STRUCT(break_info
);
991 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
992 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
993 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
994 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
995 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
996 fnum
= io
.ntcreatex
.out
.file
.fnum
;
997 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
999 torture_comment(tctx
, "unlink should generate a break, which we ack as break to none\n");
1000 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_none
, cli1
->tree
);
1001 unl
.unlink
.in
.pattern
= fname
;
1002 unl
.unlink
.in
.attrib
= 0;
1003 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1004 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1006 torture_wait_for_oplock_break(tctx
);
1007 CHECK_VAL(break_info
.count
, 1);
1008 CHECK_VAL(break_info
.fnum
, fnum
);
1009 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1010 CHECK_VAL(break_info
.failures
, 0);
1012 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1013 ZERO_STRUCT(break_info
);
1014 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1015 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1017 torture_wait_for_oplock_break(tctx
);
1018 CHECK_VAL(break_info
.count
, 0);
1020 torture_comment(tctx
, "writing should not generate a break\n");
1021 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1023 torture_wait_for_oplock_break(tctx
);
1024 CHECK_VAL(break_info
.count
, 0);
1026 smbcli_close(cli1
->tree
, fnum
);
1029 smb_raw_exit(cli1
->session
);
1030 smb_raw_exit(cli2
->session
);
1031 smbcli_deltree(cli1
->tree
, BASEDIR
);
1035 static bool test_raw_oplock_batch3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1037 const char *fname
= BASEDIR
"\\test_batch3.dat";
1041 union smb_unlink unl
;
1044 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1049 smbcli_unlink(cli1
->tree
, fname
);
1051 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1054 base ntcreatex parms
1056 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1057 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1058 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1059 io
.ntcreatex
.in
.alloc_size
= 0;
1060 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1061 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1062 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1063 io
.ntcreatex
.in
.create_options
= 0;
1064 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1065 io
.ntcreatex
.in
.security_flags
= 0;
1066 io
.ntcreatex
.in
.fname
= fname
;
1068 torture_comment(tctx
, "BATCH3: if we close on break then the unlink can succeed\n");
1069 ZERO_STRUCT(break_info
);
1070 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1071 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1072 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1073 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1074 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1075 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1076 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1077 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1079 unl
.unlink
.in
.pattern
= fname
;
1080 unl
.unlink
.in
.attrib
= 0;
1081 ZERO_STRUCT(break_info
);
1082 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1083 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1085 torture_wait_for_oplock_break(tctx
);
1086 CHECK_VAL(break_info
.count
, 1);
1087 CHECK_VAL(break_info
.fnum
, fnum
);
1088 CHECK_VAL(break_info
.level
, 1);
1089 CHECK_VAL(break_info
.failures
, 0);
1091 smbcli_close(cli1
->tree
, fnum
);
1094 smb_raw_exit(cli1
->session
);
1095 smb_raw_exit(cli2
->session
);
1096 smbcli_deltree(cli1
->tree
, BASEDIR
);
1100 static bool test_raw_oplock_batch4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1102 const char *fname
= BASEDIR
"\\test_batch4.dat";
1109 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1114 smbcli_unlink(cli1
->tree
, fname
);
1116 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1119 base ntcreatex parms
1121 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1122 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1123 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1124 io
.ntcreatex
.in
.alloc_size
= 0;
1125 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1126 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1127 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1128 io
.ntcreatex
.in
.create_options
= 0;
1129 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1130 io
.ntcreatex
.in
.security_flags
= 0;
1131 io
.ntcreatex
.in
.fname
= fname
;
1133 torture_comment(tctx
, "BATCH4: a self read should not cause a break\n");
1134 ZERO_STRUCT(break_info
);
1135 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1137 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1138 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1139 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1140 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1141 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1142 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1143 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1145 rd
.readx
.level
= RAW_READ_READX
;
1146 rd
.readx
.in
.file
.fnum
= fnum
;
1147 rd
.readx
.in
.mincnt
= 1;
1148 rd
.readx
.in
.maxcnt
= 1;
1149 rd
.readx
.in
.offset
= 0;
1150 rd
.readx
.in
.remaining
= 0;
1151 rd
.readx
.in
.read_for_execute
= false;
1152 status
= smb_raw_read(cli1
->tree
, &rd
);
1153 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1154 torture_wait_for_oplock_break(tctx
);
1155 CHECK_VAL(break_info
.count
, 0);
1156 CHECK_VAL(break_info
.failures
, 0);
1158 smbcli_close(cli1
->tree
, fnum
);
1161 smb_raw_exit(cli1
->session
);
1162 smb_raw_exit(cli2
->session
);
1163 smbcli_deltree(cli1
->tree
, BASEDIR
);
1167 static bool test_raw_oplock_batch5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1169 const char *fname
= BASEDIR
"\\test_batch5.dat";
1175 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1180 smbcli_unlink(cli1
->tree
, fname
);
1182 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1185 base ntcreatex parms
1187 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1188 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1189 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1190 io
.ntcreatex
.in
.alloc_size
= 0;
1191 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1192 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1193 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1194 io
.ntcreatex
.in
.create_options
= 0;
1195 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1196 io
.ntcreatex
.in
.security_flags
= 0;
1197 io
.ntcreatex
.in
.fname
= fname
;
1199 torture_comment(tctx
, "BATCH5: a 2nd open should give a break\n");
1200 ZERO_STRUCT(break_info
);
1201 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1203 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1204 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1205 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1206 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1207 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1208 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1209 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1211 ZERO_STRUCT(break_info
);
1213 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1214 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1215 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1217 torture_wait_for_oplock_break(tctx
);
1218 CHECK_VAL(break_info
.count
, 1);
1219 CHECK_VAL(break_info
.fnum
, fnum
);
1220 CHECK_VAL(break_info
.level
, 1);
1221 CHECK_VAL(break_info
.failures
, 0);
1223 smbcli_close(cli1
->tree
, fnum
);
1226 smb_raw_exit(cli1
->session
);
1227 smb_raw_exit(cli2
->session
);
1228 smbcli_deltree(cli1
->tree
, BASEDIR
);
1232 static bool test_raw_oplock_batch6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1234 const char *fname
= BASEDIR
"\\test_batch6.dat";
1238 uint16_t fnum
=0, fnum2
=0;
1241 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1246 smbcli_unlink(cli1
->tree
, fname
);
1248 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1249 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1252 base ntcreatex parms
1254 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1255 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1256 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1257 io
.ntcreatex
.in
.alloc_size
= 0;
1258 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1259 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1260 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1261 io
.ntcreatex
.in
.create_options
= 0;
1262 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1263 io
.ntcreatex
.in
.security_flags
= 0;
1264 io
.ntcreatex
.in
.fname
= fname
;
1266 torture_comment(tctx
, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1267 ZERO_STRUCT(break_info
);
1269 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
1270 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1271 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1272 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1273 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1274 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1275 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1276 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1277 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1279 ZERO_STRUCT(break_info
);
1281 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1282 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1283 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1284 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1286 //torture_wait_for_oplock_break(tctx);
1287 CHECK_VAL(break_info
.count
, 1);
1288 CHECK_VAL(break_info
.fnum
, fnum
);
1289 CHECK_VAL(break_info
.level
, 1);
1290 CHECK_VAL(break_info
.failures
, 0);
1291 ZERO_STRUCT(break_info
);
1293 torture_comment(tctx
, "write should trigger a break to none on both\n");
1294 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1296 /* We expect two breaks */
1297 torture_wait_for_oplock_break(tctx
);
1298 torture_wait_for_oplock_break(tctx
);
1300 CHECK_VAL(break_info
.count
, 2);
1301 CHECK_VAL(break_info
.level
, 0);
1302 CHECK_VAL(break_info
.failures
, 0);
1304 smbcli_close(cli1
->tree
, fnum
);
1305 smbcli_close(cli2
->tree
, fnum2
);
1308 smb_raw_exit(cli1
->session
);
1309 smb_raw_exit(cli2
->session
);
1310 smbcli_deltree(cli1
->tree
, BASEDIR
);
1314 static bool test_raw_oplock_batch7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1316 const char *fname
= BASEDIR
"\\test_batch7.dat";
1320 uint16_t fnum
=0, fnum2
=0;
1322 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1327 smbcli_unlink(cli1
->tree
, fname
);
1329 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1332 base ntcreatex parms
1334 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1335 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1336 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1337 io
.ntcreatex
.in
.alloc_size
= 0;
1338 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1339 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1340 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1341 io
.ntcreatex
.in
.create_options
= 0;
1342 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1343 io
.ntcreatex
.in
.security_flags
= 0;
1344 io
.ntcreatex
.in
.fname
= fname
;
1346 torture_comment(tctx
, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1347 ZERO_STRUCT(break_info
);
1348 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1350 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1351 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1352 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1353 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1354 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1355 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1356 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1357 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1358 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1360 ZERO_STRUCT(break_info
);
1362 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1363 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1364 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1365 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1366 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1367 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1368 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1370 torture_wait_for_oplock_break(tctx
);
1371 CHECK_VAL(break_info
.count
, 1);
1372 CHECK_VAL(break_info
.fnum
, fnum2
);
1373 CHECK_VAL(break_info
.level
, 1);
1374 CHECK_VAL(break_info
.failures
, 0);
1376 smbcli_close(cli2
->tree
, fnum
);
1379 smb_raw_exit(cli1
->session
);
1380 smb_raw_exit(cli2
->session
);
1381 smbcli_deltree(cli1
->tree
, BASEDIR
);
1385 static bool test_raw_oplock_batch8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1387 const char *fname
= BASEDIR
"\\test_batch8.dat";
1391 uint16_t fnum
=0, fnum2
=0;
1393 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1398 smbcli_unlink(cli1
->tree
, fname
);
1400 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1403 base ntcreatex parms
1405 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1406 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1407 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1408 io
.ntcreatex
.in
.alloc_size
= 0;
1409 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1410 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1411 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1412 io
.ntcreatex
.in
.create_options
= 0;
1413 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1414 io
.ntcreatex
.in
.security_flags
= 0;
1415 io
.ntcreatex
.in
.fname
= fname
;
1417 torture_comment(tctx
, "BATCH8: open with batch oplock\n");
1418 ZERO_STRUCT(break_info
);
1419 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1421 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1422 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1423 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1424 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1425 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1426 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1427 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1429 ZERO_STRUCT(break_info
);
1430 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
1432 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1433 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1434 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1435 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1436 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1437 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1438 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1439 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1440 torture_wait_for_oplock_break(tctx
);
1441 CHECK_VAL(break_info
.count
, 0);
1442 CHECK_VAL(break_info
.failures
, 0);
1444 smbcli_close(cli1
->tree
, fnum
);
1445 smbcli_close(cli2
->tree
, fnum2
);
1448 smb_raw_exit(cli1
->session
);
1449 smb_raw_exit(cli2
->session
);
1450 smbcli_deltree(cli1
->tree
, BASEDIR
);
1454 static bool test_raw_oplock_batch9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1456 const char *fname
= BASEDIR
"\\test_batch9.dat";
1460 uint16_t fnum
=0, fnum2
=0;
1463 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1468 smbcli_unlink(cli1
->tree
, fname
);
1470 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1473 base ntcreatex parms
1475 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1476 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1477 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1478 io
.ntcreatex
.in
.alloc_size
= 0;
1479 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1480 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1481 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1482 io
.ntcreatex
.in
.create_options
= 0;
1483 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1484 io
.ntcreatex
.in
.security_flags
= 0;
1485 io
.ntcreatex
.in
.fname
= fname
;
1487 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1489 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1490 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1491 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1492 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1493 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1494 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1495 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1496 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1497 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1499 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1501 ZERO_STRUCT(break_info
);
1502 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1504 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1505 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1506 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1507 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1508 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1509 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1510 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1511 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1512 torture_wait_for_oplock_break(tctx
);
1513 CHECK_VAL(break_info
.count
, 1);
1514 CHECK_VAL(break_info
.fnum
, fnum
);
1515 CHECK_VAL(break_info
.failures
, 0);
1516 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1517 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1518 smbcli_close(cli2
->tree
, fnum2
);
1520 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1521 ZERO_STRUCT(break_info
);
1522 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1523 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1524 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1525 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1526 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1527 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1528 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1529 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1530 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1531 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1532 torture_wait_for_oplock_break(tctx
);
1533 CHECK_VAL(break_info
.count
, 0);
1534 CHECK_VAL(break_info
.failures
, 0);
1535 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1537 ZERO_STRUCT(break_info
);
1539 torture_comment(tctx
, "write should trigger a break to none on both\n");
1540 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1542 /* We expect two breaks */
1543 torture_wait_for_oplock_break(tctx
);
1544 torture_wait_for_oplock_break(tctx
);
1546 CHECK_VAL(break_info
.count
, 2);
1547 CHECK_VAL(break_info
.level
, 0);
1548 CHECK_VAL(break_info
.failures
, 0);
1550 smbcli_close(cli1
->tree
, fnum
);
1551 smbcli_close(cli2
->tree
, fnum2
);
1554 smb_raw_exit(cli1
->session
);
1555 smb_raw_exit(cli2
->session
);
1556 smbcli_deltree(cli1
->tree
, BASEDIR
);
1560 static bool test_raw_oplock_batch10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1562 const char *fname
= BASEDIR
"\\test_batch10.dat";
1566 uint16_t fnum
=0, fnum2
=0;
1568 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1573 smbcli_unlink(cli1
->tree
, fname
);
1575 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1578 base ntcreatex parms
1580 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1581 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1582 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1583 io
.ntcreatex
.in
.alloc_size
= 0;
1584 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1585 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1586 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1587 io
.ntcreatex
.in
.create_options
= 0;
1588 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1589 io
.ntcreatex
.in
.security_flags
= 0;
1590 io
.ntcreatex
.in
.fname
= fname
;
1592 torture_comment(tctx
, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1593 ZERO_STRUCT(break_info
);
1594 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1595 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1596 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1597 NTCREATEX_SHARE_ACCESS_WRITE
|
1598 NTCREATEX_SHARE_ACCESS_DELETE
;
1599 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1600 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1601 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1602 torture_wait_for_oplock_break(tctx
);
1603 CHECK_VAL(break_info
.count
, 0);
1604 CHECK_VAL(break_info
.failures
, 0);
1605 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1607 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1609 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1610 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1611 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1612 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1613 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1614 NTCREATEX_SHARE_ACCESS_WRITE
|
1615 NTCREATEX_SHARE_ACCESS_DELETE
;
1616 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1617 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1618 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1619 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1620 torture_wait_for_oplock_break(tctx
);
1621 CHECK_VAL(break_info
.count
, 0);
1622 CHECK_VAL(break_info
.failures
, 0);
1623 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1625 torture_comment(tctx
, "write should trigger a break to none\n");
1628 wr
.write
.level
= RAW_WRITE_WRITE
;
1629 wr
.write
.in
.file
.fnum
= fnum
;
1630 wr
.write
.in
.count
= 1;
1631 wr
.write
.in
.offset
= 0;
1632 wr
.write
.in
.remaining
= 0;
1633 wr
.write
.in
.data
= (const uint8_t *)"x";
1634 status
= smb_raw_write(cli1
->tree
, &wr
);
1635 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1638 torture_wait_for_oplock_break(tctx
);
1640 CHECK_VAL(break_info
.count
, 1);
1641 CHECK_VAL(break_info
.fnum
, fnum2
);
1642 CHECK_VAL(break_info
.level
, 0);
1643 CHECK_VAL(break_info
.failures
, 0);
1645 smbcli_close(cli1
->tree
, fnum
);
1646 smbcli_close(cli2
->tree
, fnum2
);
1649 smb_raw_exit(cli1
->session
);
1650 smb_raw_exit(cli2
->session
);
1651 smbcli_deltree(cli1
->tree
, BASEDIR
);
1655 static bool test_raw_oplock_batch11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1657 const char *fname
= BASEDIR
"\\test_batch11.dat";
1661 union smb_setfileinfo sfi
;
1664 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1669 smbcli_unlink(cli1
->tree
, fname
);
1671 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1674 base ntcreatex parms
1676 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1677 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1678 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1679 io
.ntcreatex
.in
.alloc_size
= 0;
1680 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1681 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
1682 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1683 io
.ntcreatex
.in
.create_options
= 0;
1684 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1685 io
.ntcreatex
.in
.security_flags
= 0;
1686 io
.ntcreatex
.in
.fname
= fname
;
1688 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1689 torture_comment(tctx
, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1691 ZERO_STRUCT(break_info
);
1693 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1694 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1695 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1696 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1697 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1698 NTCREATEX_SHARE_ACCESS_WRITE
|
1699 NTCREATEX_SHARE_ACCESS_DELETE
;
1700 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1701 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1702 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1703 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1704 torture_wait_for_oplock_break(tctx
);
1705 CHECK_VAL(break_info
.count
, 0);
1706 CHECK_VAL(break_info
.failures
, 0);
1707 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1710 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
1711 sfi
.generic
.in
.file
.path
= fname
;
1712 sfi
.end_of_file_info
.in
.size
= 100;
1714 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1715 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1717 torture_wait_for_oplock_break(tctx
);
1718 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1719 CHECK_VAL(break_info
.failures
, 0);
1720 CHECK_VAL(break_info
.level
, 0);
1722 smbcli_close(cli1
->tree
, fnum
);
1725 smb_raw_exit(cli1
->session
);
1726 smb_raw_exit(cli2
->session
);
1727 smbcli_deltree(cli1
->tree
, BASEDIR
);
1731 static bool test_raw_oplock_batch12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1733 const char *fname
= BASEDIR
"\\test_batch12.dat";
1737 union smb_setfileinfo sfi
;
1740 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1745 smbcli_unlink(cli1
->tree
, fname
);
1747 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1750 base ntcreatex parms
1752 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1753 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1754 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1755 io
.ntcreatex
.in
.alloc_size
= 0;
1756 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1757 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1758 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1759 io
.ntcreatex
.in
.create_options
= 0;
1760 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1761 io
.ntcreatex
.in
.security_flags
= 0;
1762 io
.ntcreatex
.in
.fname
= fname
;
1764 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1765 torture_comment(tctx
, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1767 ZERO_STRUCT(break_info
);
1768 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1770 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1771 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1772 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1773 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1774 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1775 NTCREATEX_SHARE_ACCESS_WRITE
|
1776 NTCREATEX_SHARE_ACCESS_DELETE
;
1777 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1778 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1779 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1780 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1781 torture_wait_for_oplock_break(tctx
);
1782 CHECK_VAL(break_info
.count
, 0);
1783 CHECK_VAL(break_info
.failures
, 0);
1784 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1787 sfi
.generic
.level
= SMB_SFILEINFO_ALLOCATION_INFORMATION
;
1788 sfi
.generic
.in
.file
.path
= fname
;
1789 sfi
.allocation_info
.in
.alloc_size
= 65536 * 8;
1791 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1792 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1794 torture_wait_for_oplock_break(tctx
);
1795 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1796 CHECK_VAL(break_info
.failures
, 0);
1797 CHECK_VAL(break_info
.level
, 0);
1799 smbcli_close(cli1
->tree
, fnum
);
1802 smb_raw_exit(cli1
->session
);
1803 smb_raw_exit(cli2
->session
);
1804 smbcli_deltree(cli1
->tree
, BASEDIR
);
1808 static bool test_raw_oplock_batch13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1810 const char *fname
= BASEDIR
"\\test_batch13.dat";
1814 uint16_t fnum
=0, fnum2
=0;
1816 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1821 smbcli_unlink(cli1
->tree
, fname
);
1823 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1824 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1827 base ntcreatex parms
1829 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1830 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1831 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1832 io
.ntcreatex
.in
.alloc_size
= 0;
1833 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1834 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1835 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1836 io
.ntcreatex
.in
.create_options
= 0;
1837 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1838 io
.ntcreatex
.in
.security_flags
= 0;
1839 io
.ntcreatex
.in
.fname
= fname
;
1841 torture_comment(tctx
, "BATCH13: open with batch oplock\n");
1842 ZERO_STRUCT(break_info
);
1844 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1845 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1846 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1847 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1848 NTCREATEX_SHARE_ACCESS_WRITE
|
1849 NTCREATEX_SHARE_ACCESS_DELETE
;
1850 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1851 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1852 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1853 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1855 ZERO_STRUCT(break_info
);
1857 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1859 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1860 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1861 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1862 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1863 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1864 NTCREATEX_SHARE_ACCESS_WRITE
|
1865 NTCREATEX_SHARE_ACCESS_DELETE
;
1866 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1867 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1868 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1869 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1870 torture_wait_for_oplock_break(tctx
);
1871 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1872 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1873 CHECK_VAL(break_info
.failures
, 0);
1875 smbcli_close(cli1
->tree
, fnum
);
1876 smbcli_close(cli2
->tree
, fnum2
);
1879 smb_raw_exit(cli1
->session
);
1880 smb_raw_exit(cli2
->session
);
1881 smbcli_deltree(cli1
->tree
, BASEDIR
);
1885 static bool test_raw_oplock_batch14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1887 const char *fname
= BASEDIR
"\\test_batch14.dat";
1891 uint16_t fnum
=0, fnum2
=0;
1893 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1898 smbcli_unlink(cli1
->tree
, fname
);
1900 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1903 base ntcreatex parms
1905 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1906 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1907 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1908 io
.ntcreatex
.in
.alloc_size
= 0;
1909 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1910 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1911 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1912 io
.ntcreatex
.in
.create_options
= 0;
1913 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1914 io
.ntcreatex
.in
.security_flags
= 0;
1915 io
.ntcreatex
.in
.fname
= fname
;
1917 torture_comment(tctx
, "BATCH14: open with batch oplock\n");
1918 ZERO_STRUCT(break_info
);
1920 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1921 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1922 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1923 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1924 NTCREATEX_SHARE_ACCESS_WRITE
|
1925 NTCREATEX_SHARE_ACCESS_DELETE
;
1926 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1927 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1928 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1929 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1931 ZERO_STRUCT(break_info
);
1933 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1935 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1936 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1937 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1938 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1939 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1940 NTCREATEX_SHARE_ACCESS_WRITE
|
1941 NTCREATEX_SHARE_ACCESS_DELETE
;
1942 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1943 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1944 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1945 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1946 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1948 torture_wait_for_oplock_break(tctx
);
1949 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1950 CHECK_VAL(break_info
.failures
, 0);
1952 smbcli_close(cli1
->tree
, fnum
);
1953 smbcli_close(cli2
->tree
, fnum2
);
1955 smb_raw_exit(cli1
->session
);
1956 smb_raw_exit(cli2
->session
);
1957 smbcli_deltree(cli1
->tree
, BASEDIR
);
1961 static bool test_raw_oplock_batch15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1963 const char *fname
= BASEDIR
"\\test_batch15.dat";
1967 union smb_fileinfo qfi
;
1970 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1975 smbcli_unlink(cli1
->tree
, fname
);
1977 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1980 base ntcreatex parms
1982 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1983 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1984 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1985 io
.ntcreatex
.in
.alloc_size
= 0;
1986 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1987 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1988 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1989 io
.ntcreatex
.in
.create_options
= 0;
1990 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1991 io
.ntcreatex
.in
.security_flags
= 0;
1992 io
.ntcreatex
.in
.fname
= fname
;
1994 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1995 torture_comment(tctx
, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1997 ZERO_STRUCT(break_info
);
1999 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2000 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2001 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2002 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2003 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2004 NTCREATEX_SHARE_ACCESS_WRITE
|
2005 NTCREATEX_SHARE_ACCESS_DELETE
;
2006 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2007 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2008 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2009 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2010 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2012 torture_wait_for_oplock_break(tctx
);
2013 CHECK_VAL(break_info
.count
, 0);
2014 CHECK_VAL(break_info
.failures
, 0);
2015 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2018 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2019 qfi
.generic
.in
.file
.path
= fname
;
2021 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
2022 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2024 torture_wait_for_oplock_break(tctx
);
2025 CHECK_VAL(break_info
.count
, 0);
2027 smbcli_close(cli1
->tree
, fnum
);
2030 smb_raw_exit(cli1
->session
);
2031 smb_raw_exit(cli2
->session
);
2032 smbcli_deltree(cli1
->tree
, BASEDIR
);
2036 static bool test_raw_oplock_batch16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2038 const char *fname
= BASEDIR
"\\test_batch16.dat";
2042 uint16_t fnum
=0, fnum2
=0;
2044 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2049 smbcli_unlink(cli1
->tree
, fname
);
2051 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2052 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2055 base ntcreatex parms
2057 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2058 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2059 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2060 io
.ntcreatex
.in
.alloc_size
= 0;
2061 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2062 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2063 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2064 io
.ntcreatex
.in
.create_options
= 0;
2065 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2066 io
.ntcreatex
.in
.security_flags
= 0;
2067 io
.ntcreatex
.in
.fname
= fname
;
2069 torture_comment(tctx
, "BATCH16: open with batch oplock\n");
2070 ZERO_STRUCT(break_info
);
2072 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2073 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2074 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2075 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2076 NTCREATEX_SHARE_ACCESS_WRITE
|
2077 NTCREATEX_SHARE_ACCESS_DELETE
;
2078 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2079 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2080 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2081 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2083 ZERO_STRUCT(break_info
);
2085 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2087 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2088 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2089 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2090 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2091 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2092 NTCREATEX_SHARE_ACCESS_WRITE
|
2093 NTCREATEX_SHARE_ACCESS_DELETE
;
2094 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
2095 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2096 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2097 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2098 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2100 torture_wait_for_oplock_break(tctx
);
2101 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2102 CHECK_VAL(break_info
.failures
, 0);
2104 smbcli_close(cli1
->tree
, fnum
);
2105 smbcli_close(cli2
->tree
, fnum2
);
2108 smb_raw_exit(cli1
->session
);
2109 smb_raw_exit(cli2
->session
);
2110 smbcli_deltree(cli1
->tree
, BASEDIR
);
2114 static bool test_raw_oplock_batch17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2116 const char *fname1
= BASEDIR
"\\test_batch17_1.dat";
2117 const char *fname2
= BASEDIR
"\\test_batch17_2.dat";
2121 union smb_rename rn
;
2124 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2129 smbcli_unlink(cli1
->tree
, fname1
);
2130 smbcli_unlink(cli1
->tree
, fname2
);
2132 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2135 base ntcreatex parms
2137 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2138 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2139 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2140 io
.ntcreatex
.in
.alloc_size
= 0;
2141 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2142 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2143 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2144 io
.ntcreatex
.in
.create_options
= 0;
2145 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2146 io
.ntcreatex
.in
.security_flags
= 0;
2147 io
.ntcreatex
.in
.fname
= fname1
;
2149 torture_comment(tctx
, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2151 ZERO_STRUCT(break_info
);
2152 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2153 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2154 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2156 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2157 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2158 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2159 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2161 torture_comment(tctx
, "rename should trigger a break\n");
2163 rn
.generic
.level
= RAW_RENAME_RENAME
;
2164 rn
.rename
.in
.pattern1
= fname1
;
2165 rn
.rename
.in
.pattern2
= fname2
;
2166 rn
.rename
.in
.attrib
= 0;
2168 torture_comment(tctx
, "trying rename while first file open\n");
2169 status
= smb_raw_rename(cli2
->tree
, &rn
);
2170 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2172 torture_wait_for_oplock_break(tctx
);
2173 CHECK_VAL(break_info
.count
, 1);
2174 CHECK_VAL(break_info
.failures
, 0);
2175 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2177 smbcli_close(cli1
->tree
, fnum
);
2180 smb_raw_exit(cli1
->session
);
2181 smb_raw_exit(cli2
->session
);
2182 smbcli_deltree(cli1
->tree
, BASEDIR
);
2186 static bool test_raw_oplock_batch18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2188 const char *fname1
= BASEDIR
"\\test_batch18_1.dat";
2189 const char *fname2
= BASEDIR
"\\test_batch18_2.dat";
2193 union smb_rename rn
;
2196 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2201 smbcli_unlink(cli1
->tree
, fname1
);
2202 smbcli_unlink(cli1
->tree
, fname2
);
2204 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2207 base ntcreatex parms
2209 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2210 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2211 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2212 io
.ntcreatex
.in
.alloc_size
= 0;
2213 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2214 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2215 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2216 io
.ntcreatex
.in
.create_options
= 0;
2217 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2218 io
.ntcreatex
.in
.security_flags
= 0;
2219 io
.ntcreatex
.in
.fname
= fname1
;
2221 torture_comment(tctx
, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2223 ZERO_STRUCT(break_info
);
2224 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2225 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2226 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2228 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2229 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2230 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2231 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2233 torture_comment(tctx
, "ntrename should trigger a break\n");
2235 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
2236 rn
.ntrename
.in
.attrib
= 0;
2237 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
2238 rn
.ntrename
.in
.old_name
= fname1
;
2239 rn
.ntrename
.in
.new_name
= fname2
;
2240 torture_comment(tctx
, "trying rename while first file open\n");
2241 status
= smb_raw_rename(cli2
->tree
, &rn
);
2242 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2244 torture_wait_for_oplock_break(tctx
);
2245 CHECK_VAL(break_info
.count
, 1);
2246 CHECK_VAL(break_info
.failures
, 0);
2247 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2249 smbcli_close(cli1
->tree
, fnum
);
2252 smb_raw_exit(cli1
->session
);
2253 smb_raw_exit(cli2
->session
);
2254 smbcli_deltree(cli1
->tree
, BASEDIR
);
2258 static bool test_raw_oplock_batch19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2260 const char *fname1
= BASEDIR
"\\test_batch19_1.dat";
2261 const char *fname2
= BASEDIR
"\\test_batch19_2.dat";
2262 const char *fname3
= BASEDIR
"\\test_batch19_3.dat";
2266 union smb_fileinfo qfi
;
2267 union smb_setfileinfo sfi
;
2270 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2275 smbcli_unlink(cli1
->tree
, fname1
);
2276 smbcli_unlink(cli1
->tree
, fname2
);
2277 smbcli_unlink(cli1
->tree
, fname3
);
2279 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2282 base ntcreatex parms
2284 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2285 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2286 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2287 io
.ntcreatex
.in
.alloc_size
= 0;
2288 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2289 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2290 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2291 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2292 io
.ntcreatex
.in
.create_options
= 0;
2293 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2294 io
.ntcreatex
.in
.security_flags
= 0;
2295 io
.ntcreatex
.in
.fname
= fname1
;
2297 torture_comment(tctx
, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2298 ZERO_STRUCT(break_info
);
2299 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2300 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2301 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2302 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2303 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2304 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2305 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2307 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
2310 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2311 sfi
.generic
.in
.file
.path
= fname1
;
2312 sfi
.rename_information
.in
.overwrite
= 0;
2313 sfi
.rename_information
.in
.root_fid
= 0;
2314 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2316 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2317 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2319 torture_wait_for_oplock_break(tctx
);
2321 CHECK_VAL(break_info
.failures
, 0);
2323 if (TARGET_IS_WINXP(tctx
)) {
2324 /* Win XP breaks to level2. */
2325 CHECK_VAL(break_info
.count
, 1);
2326 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2327 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2328 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2329 /* Win2K3/2k8 incorrectly doesn't break at all. */
2330 CHECK_VAL(break_info
.count
, 0);
2332 /* win7/2k8r2 break to none. */
2333 CHECK_VAL(break_info
.count
, 1);
2334 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2338 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2339 qfi
.generic
.in
.file
.fnum
= fnum
;
2341 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2342 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2343 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2345 /* Close and re-open file with oplock. */
2346 smbcli_close(cli1
->tree
, fnum
);
2347 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2348 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2349 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2350 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2352 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
2353 "should not trigger a break nor a violation\n");
2354 ZERO_STRUCT(break_info
);
2356 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2357 sfi
.generic
.in
.file
.fnum
= fnum
;
2358 sfi
.rename_information
.in
.overwrite
= 0;
2359 sfi
.rename_information
.in
.root_fid
= 0;
2360 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2362 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2363 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2365 torture_wait_for_oplock_break(tctx
);
2366 if (TARGET_IS_WINXP(tctx
)) {
2367 /* XP incorrectly breaks to level2. */
2368 CHECK_VAL(break_info
.count
, 1);
2369 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2371 CHECK_VAL(break_info
.count
, 0);
2375 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2376 qfi
.generic
.in
.file
.fnum
= fnum
;
2378 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2379 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2380 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2383 smbcli_close(cli1
->tree
, fnum
);
2384 smb_raw_exit(cli1
->session
);
2385 smb_raw_exit(cli2
->session
);
2386 smbcli_deltree(cli1
->tree
, BASEDIR
);
2390 /****************************************************
2391 Called from raw-rename - we need oplock handling for
2392 this test so this is why it's in oplock.c, not rename.c
2393 ****************************************************/
2395 bool test_trans2rename(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2397 const char *fname1
= BASEDIR
"\\test_trans2rename_1.dat";
2398 const char *fname2
= BASEDIR
"\\test_trans2rename_2.dat";
2399 const char *fname3
= BASEDIR
"\\test_trans2rename_3.dat";
2403 union smb_fileinfo qfi
;
2404 union smb_setfileinfo sfi
;
2407 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2412 smbcli_unlink(cli1
->tree
, fname1
);
2413 smbcli_unlink(cli1
->tree
, fname2
);
2414 smbcli_unlink(cli1
->tree
, fname3
);
2416 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2419 base ntcreatex parms
2421 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2422 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2423 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2424 io
.ntcreatex
.in
.alloc_size
= 0;
2425 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2426 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2427 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2428 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2429 io
.ntcreatex
.in
.create_options
= 0;
2430 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2431 io
.ntcreatex
.in
.security_flags
= 0;
2432 io
.ntcreatex
.in
.fname
= fname1
;
2434 torture_comment(tctx
, "open a file with an exclusive oplock (share mode: none)\n");
2435 ZERO_STRUCT(break_info
);
2436 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2437 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2438 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2439 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2440 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2441 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2443 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2445 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2446 sfi
.generic
.in
.file
.path
= fname1
;
2447 sfi
.rename_information
.in
.overwrite
= 0;
2448 sfi
.rename_information
.in
.root_fid
= 0;
2449 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2451 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2453 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2455 torture_wait_for_oplock_break(tctx
);
2456 CHECK_VAL(break_info
.count
, 0);
2459 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2460 qfi
.generic
.in
.file
.fnum
= fnum
;
2462 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2463 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2464 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2466 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2468 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2469 sfi
.generic
.in
.file
.fnum
= fnum
;
2470 sfi
.rename_information
.in
.overwrite
= 0;
2471 sfi
.rename_information
.in
.root_fid
= 0;
2472 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2474 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2475 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2477 torture_wait_for_oplock_break(tctx
);
2478 CHECK_VAL(break_info
.count
, 0);
2481 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2482 qfi
.generic
.in
.file
.fnum
= fnum
;
2484 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2485 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2486 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2489 smbcli_close(cli1
->tree
, fnum
);
2490 smb_raw_exit(cli1
->session
);
2491 smb_raw_exit(cli2
->session
);
2492 smbcli_deltree(cli1
->tree
, BASEDIR
);
2496 /****************************************************
2497 Called from raw-rename - we need oplock handling for
2498 this test so this is why it's in oplock.c, not rename.c
2499 ****************************************************/
2501 bool test_nttransrename(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
2503 const char *fname1
= BASEDIR
"\\test_nttransrename_1.dat";
2504 const char *fname2
= BASEDIR
"\\test_nttransrename_2.dat";
2508 union smb_fileinfo qfi
, qpi
;
2509 union smb_rename rn
;
2512 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2517 smbcli_unlink(cli1
->tree
, fname1
);
2518 smbcli_unlink(cli1
->tree
, fname2
);
2520 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2523 base ntcreatex parms
2525 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2526 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2527 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2528 io
.ntcreatex
.in
.alloc_size
= 0;
2529 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2530 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2531 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2532 io
.ntcreatex
.in
.create_options
= 0;
2533 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2534 io
.ntcreatex
.in
.security_flags
= 0;
2535 io
.ntcreatex
.in
.fname
= fname1
;
2537 torture_comment(tctx
, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2538 ZERO_STRUCT(break_info
);
2539 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2540 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2541 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2542 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2543 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2544 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2546 torture_comment(tctx
, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2548 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2549 rn
.nttrans
.in
.file
.fnum
= fnum
;
2550 rn
.nttrans
.in
.flags
= 0;
2551 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2553 status
= smb_raw_rename(cli1
->tree
, &rn
);
2554 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2556 torture_wait_for_oplock_break(tctx
);
2557 CHECK_VAL(break_info
.count
, 0);
2559 /* w2k3 does nothing, it doesn't rename the file */
2560 torture_comment(tctx
, "nttrans_rename: the server should have done nothing\n");
2562 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2563 qfi
.generic
.in
.file
.fnum
= fnum
;
2565 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2566 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2567 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname1
);
2570 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2571 qpi
.generic
.in
.file
.path
= fname1
;
2573 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2574 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2575 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2578 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2579 qpi
.generic
.in
.file
.path
= fname2
;
2581 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2582 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2584 torture_comment(tctx
, "nttrans_rename: after closing the file the file is still not renamed\n");
2585 status
= smbcli_close(cli1
->tree
, fnum
);
2586 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2589 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2590 qpi
.generic
.in
.file
.path
= fname1
;
2592 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2593 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2594 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2597 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2598 qpi
.generic
.in
.file
.path
= fname2
;
2600 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2601 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2603 torture_comment(tctx
, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2605 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2606 rn
.nttrans
.in
.file
.fnum
= fnum
+1;
2607 rn
.nttrans
.in
.flags
= 0;
2608 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2610 status
= smb_raw_rename(cli1
->tree
, &rn
);
2612 CHECK_STATUS(tctx
, status
, NT_STATUS_INVALID_HANDLE
);
2615 smb_raw_exit(cli1
->session
);
2616 smbcli_deltree(cli1
->tree
, BASEDIR
);
2621 static bool test_raw_oplock_batch20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2623 const char *fname1
= BASEDIR
"\\test_batch20_1.dat";
2624 const char *fname2
= BASEDIR
"\\test_batch20_2.dat";
2625 const char *fname3
= BASEDIR
"\\test_batch20_3.dat";
2629 union smb_fileinfo qfi
;
2630 union smb_setfileinfo sfi
;
2631 uint16_t fnum
=0,fnum2
=0;
2633 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2638 smbcli_unlink(cli1
->tree
, fname1
);
2639 smbcli_unlink(cli1
->tree
, fname2
);
2640 smbcli_unlink(cli1
->tree
, fname3
);
2642 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2645 base ntcreatex parms
2647 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2648 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2649 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2650 io
.ntcreatex
.in
.alloc_size
= 0;
2651 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2652 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2653 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2654 io
.ntcreatex
.in
.create_options
= 0;
2655 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2656 io
.ntcreatex
.in
.security_flags
= 0;
2657 io
.ntcreatex
.in
.fname
= fname1
;
2659 torture_comment(tctx
, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2660 ZERO_STRUCT(break_info
);
2661 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2662 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2663 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2664 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2665 NTCREATEX_SHARE_ACCESS_WRITE
|
2666 NTCREATEX_SHARE_ACCESS_DELETE
;
2667 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2668 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2669 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2670 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2673 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2674 sfi
.generic
.in
.file
.path
= fname1
;
2675 sfi
.rename_information
.in
.overwrite
= 0;
2676 sfi
.rename_information
.in
.root_fid
= 0;
2677 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2679 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2680 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2682 torture_wait_for_oplock_break(tctx
);
2683 CHECK_VAL(break_info
.failures
, 0);
2685 if (TARGET_IS_WINXP(tctx
)) {
2686 /* Win XP breaks to level2. */
2687 CHECK_VAL(break_info
.count
, 1);
2688 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2689 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2690 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2691 /* Win2K3/2k8 incorrectly doesn't break at all. */
2692 CHECK_VAL(break_info
.count
, 0);
2694 /* win7/2k8r2 break to none. */
2695 CHECK_VAL(break_info
.count
, 1);
2696 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2700 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2701 qfi
.generic
.in
.file
.fnum
= fnum
;
2703 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2704 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2705 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2707 torture_comment(tctx
, "open a file with the new name an batch oplock (share mode: all)\n");
2708 ZERO_STRUCT(break_info
);
2709 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2710 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2711 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2712 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2713 NTCREATEX_SHARE_ACCESS_WRITE
|
2714 NTCREATEX_SHARE_ACCESS_DELETE
;
2715 io
.ntcreatex
.in
.fname
= fname2
;
2716 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2717 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2718 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2719 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2721 torture_wait_for_oplock_break(tctx
);
2723 if (TARGET_IS_WINXP(tctx
)) {
2724 /* XP broke to level2, and doesn't break again. */
2725 CHECK_VAL(break_info
.count
, 0);
2726 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2727 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2728 /* Win2K3 incorrectly didn't break before so break now. */
2729 CHECK_VAL(break_info
.count
, 1);
2730 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2732 /* win7/2k8r2 broke to none, and doesn't break again. */
2733 CHECK_VAL(break_info
.count
, 0);
2736 ZERO_STRUCT(break_info
);
2739 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2740 sfi
.generic
.in
.file
.fnum
= fnum
;
2741 sfi
.rename_information
.in
.overwrite
= 0;
2742 sfi
.rename_information
.in
.root_fid
= 0;
2743 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2745 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2746 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2748 torture_wait_for_oplock_break(tctx
);
2749 CHECK_VAL(break_info
.count
, 0);
2752 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2753 qfi
.generic
.in
.file
.fnum
= fnum
;
2755 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2756 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2757 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2760 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2761 qfi
.generic
.in
.file
.fnum
= fnum2
;
2763 status
= smb_raw_fileinfo(cli2
->tree
, tctx
, &qfi
);
2764 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2765 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2769 smbcli_close(cli1
->tree
, fnum
);
2770 smbcli_close(cli2
->tree
, fnum2
);
2771 smb_raw_exit(cli1
->session
);
2772 smb_raw_exit(cli2
->session
);
2773 smbcli_deltree(cli1
->tree
, BASEDIR
);
2777 static bool test_raw_oplock_batch21(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2779 const char *fname
= BASEDIR
"\\test_batch21.dat";
2788 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2793 smbcli_unlink(cli1
->tree
, fname
);
2795 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2798 base ntcreatex parms
2800 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2801 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2802 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2803 io
.ntcreatex
.in
.alloc_size
= 0;
2804 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2805 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2806 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2807 io
.ntcreatex
.in
.create_options
= 0;
2808 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2809 io
.ntcreatex
.in
.security_flags
= 0;
2810 io
.ntcreatex
.in
.fname
= fname
;
2813 with a batch oplock we get a break
2815 torture_comment(tctx
, "BATCH21: open with batch oplock\n");
2816 ZERO_STRUCT(break_info
);
2817 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2818 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2819 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2820 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2821 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2822 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2823 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2825 torture_comment(tctx
, "writing should not generate a break\n");
2826 wr
= smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
2828 CHECK_STATUS(tctx
, smbcli_nt_error(cli1
->tree
), NT_STATUS_OK
);
2831 e
.in
.repeat_count
= 1;
2832 status
= smb_raw_echo(cli1
->transport
, &e
);
2833 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2835 torture_wait_for_oplock_break(tctx
);
2836 CHECK_VAL(break_info
.count
, 0);
2838 smbcli_close(cli1
->tree
, fnum
);
2841 smb_raw_exit(cli1
->session
);
2842 smb_raw_exit(cli2
->session
);
2843 smbcli_deltree(cli1
->tree
, BASEDIR
);
2847 static bool test_raw_oplock_batch22(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2849 const char *fname
= BASEDIR
"\\test_batch22.dat";
2853 uint16_t fnum
= 0, fnum2
= 0, fnum3
= 0;
2855 int timeout
= torture_setting_int(tctx
, "oplocktimeout", 30);
2858 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2863 smbcli_unlink(cli1
->tree
, fname
);
2865 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2867 base ntcreatex parms
2869 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2870 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2871 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2872 io
.ntcreatex
.in
.alloc_size
= 0;
2873 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2874 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2875 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2876 io
.ntcreatex
.in
.create_options
= 0;
2877 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2878 io
.ntcreatex
.in
.security_flags
= 0;
2879 io
.ntcreatex
.in
.fname
= fname
;
2882 with a batch oplock we get a break
2884 torture_comment(tctx
, "BATCH22: open with batch oplock\n");
2885 ZERO_STRUCT(break_info
);
2886 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2887 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2888 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2889 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2890 NTCREATEX_SHARE_ACCESS_WRITE
|
2891 NTCREATEX_SHARE_ACCESS_DELETE
;
2892 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2893 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2894 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2895 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2897 torture_comment(tctx
, "a 2nd open should not succeed after the oplock "
2899 tv
= timeval_current();
2900 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
, cli1
->tree
);
2901 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2903 if (TARGET_IS_W2K3(tctx
)) {
2904 /* 2k3 has an issue here. xp/win7 are ok. */
2905 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2907 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2910 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2912 torture_wait_for_oplock_break(tctx
);
2913 te
= (int)timeval_elapsed(&tv
);
2916 * Some servers detect clients that let oplocks timeout, so this check
2917 * only shows a warning message instead failing the test to eliminate
2918 * failures from repeated runs of the test. This isn't ideal, but
2919 * it's better than not running the test at all.
2921 CHECK_RANGE(te
, timeout
- 1, timeout
+ 15);
2923 CHECK_VAL(break_info
.count
, 1);
2924 CHECK_VAL(break_info
.fnum
, fnum
);
2925 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2926 CHECK_VAL(break_info
.failures
, 0);
2927 ZERO_STRUCT(break_info
);
2929 torture_comment(tctx
, "a 2nd open should succeed after the oplock "
2930 "release without break\n");
2931 tv
= timeval_current();
2932 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2933 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2934 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2936 /* Samba 3.6.0 and above behave as Windows. */
2937 if (TARGET_IS_SAMBA3(tctx
)) {
2938 /* samba3 doesn't grant additional oplocks to bad clients. */
2939 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
2941 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
2942 LEVEL_II_OPLOCK_RETURN
);
2945 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
2946 LEVEL_II_OPLOCK_RETURN
);
2948 torture_wait_for_oplock_break(tctx
);
2949 te
= (int)timeval_elapsed(&tv
);
2950 /* it should come in without delay */
2951 CHECK_RANGE(te
+1, 0, timeout
);
2952 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
2954 CHECK_VAL(break_info
.count
, 0);
2956 smbcli_close(cli1
->tree
, fnum
);
2957 smbcli_close(cli1
->tree
, fnum2
);
2958 smbcli_close(cli1
->tree
, fnum3
);
2961 smb_raw_exit(cli1
->session
);
2962 smb_raw_exit(cli2
->session
);
2963 smbcli_deltree(cli1
->tree
, BASEDIR
);
2967 static bool test_raw_oplock_batch23(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2969 const char *fname
= BASEDIR
"\\test_batch23.dat";
2973 uint16_t fnum
=0, fnum2
=0,fnum3
=0;
2974 struct smbcli_state
*cli3
= NULL
;
2976 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2981 smbcli_unlink(cli1
->tree
, fname
);
2983 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
2984 CHECK_VAL(ret
, true);
2986 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2987 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
2988 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
2991 base ntcreatex parms
2993 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2994 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2995 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2996 io
.ntcreatex
.in
.alloc_size
= 0;
2997 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2998 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2999 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3000 io
.ntcreatex
.in
.create_options
= 0;
3001 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3002 io
.ntcreatex
.in
.security_flags
= 0;
3003 io
.ntcreatex
.in
.fname
= fname
;
3005 torture_comment(tctx
, "BATCH23: a open and ask for a batch oplock\n");
3006 ZERO_STRUCT(break_info
);
3008 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3009 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3010 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3011 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3012 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3013 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3014 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3015 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3016 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3018 ZERO_STRUCT(break_info
);
3020 torture_comment(tctx
, "a 2nd open without level2 oplock support should generate a break to level2\n");
3021 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3022 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3023 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3024 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3026 torture_wait_for_oplock_break(tctx
);
3027 CHECK_VAL(break_info
.count
, 1);
3028 CHECK_VAL(break_info
.fnum
, fnum
);
3029 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3030 CHECK_VAL(break_info
.failures
, 0);
3032 ZERO_STRUCT(break_info
);
3034 torture_comment(tctx
, "a 3rd open with level2 oplock support should not generate a break\n");
3035 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3036 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3037 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3038 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3040 torture_wait_for_oplock_break(tctx
);
3041 CHECK_VAL(break_info
.count
, 0);
3043 smbcli_close(cli1
->tree
, fnum
);
3044 smbcli_close(cli2
->tree
, fnum2
);
3045 smbcli_close(cli3
->tree
, fnum3
);
3048 smb_raw_exit(cli1
->session
);
3049 smb_raw_exit(cli2
->session
);
3050 smb_raw_exit(cli3
->session
);
3051 smbcli_deltree(cli1
->tree
, BASEDIR
);
3055 static bool test_raw_oplock_batch24(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3057 const char *fname
= BASEDIR
"\\test_batch24.dat";
3061 uint16_t fnum2
=0,fnum3
=0;
3062 struct smbcli_state
*cli3
= NULL
;
3064 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3069 smbcli_unlink(cli1
->tree
, fname
);
3071 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3072 CHECK_VAL(ret
, true);
3074 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3075 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3076 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3079 base ntcreatex parms
3081 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3082 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3083 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3084 io
.ntcreatex
.in
.alloc_size
= 0;
3085 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3086 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3087 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3088 io
.ntcreatex
.in
.create_options
= 0;
3089 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3090 io
.ntcreatex
.in
.security_flags
= 0;
3091 io
.ntcreatex
.in
.fname
= fname
;
3093 torture_comment(tctx
, "BATCH24: a open without level support and ask for a batch oplock\n");
3094 ZERO_STRUCT(break_info
);
3096 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3097 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3098 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3099 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3100 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3101 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3102 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3103 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3104 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3106 ZERO_STRUCT(break_info
);
3108 torture_comment(tctx
, "a 2nd open with level2 oplock support should generate a break to none\n");
3109 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3110 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3111 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3112 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3114 torture_wait_for_oplock_break(tctx
);
3115 CHECK_VAL(break_info
.count
, 1);
3116 CHECK_VAL(break_info
.fnum
, fnum3
);
3117 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3118 CHECK_VAL(break_info
.failures
, 0);
3120 smbcli_close(cli3
->tree
, fnum3
);
3121 smbcli_close(cli2
->tree
, fnum2
);
3124 smb_raw_exit(cli1
->session
);
3125 smb_raw_exit(cli2
->session
);
3126 smb_raw_exit(cli3
->session
);
3127 smbcli_deltree(cli1
->tree
, BASEDIR
);
3131 static bool test_raw_oplock_batch25(struct torture_context
*tctx
,
3132 struct smbcli_state
*cli1
,
3133 struct smbcli_state
*cli2
)
3135 const char *fname
= BASEDIR
"\\test_batch25.dat";
3139 union smb_setfileinfo sfi
;
3142 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3147 smbcli_unlink(cli1
->tree
, fname
);
3149 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3152 base ntcreatex parms
3154 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3155 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3156 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3157 io
.ntcreatex
.in
.alloc_size
= 0;
3158 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3159 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3160 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3161 io
.ntcreatex
.in
.create_options
= 0;
3162 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3163 io
.ntcreatex
.in
.security_flags
= 0;
3164 io
.ntcreatex
.in
.fname
= fname
;
3166 torture_comment(tctx
, "BATCH25: open a file with an batch oplock "
3167 "(share mode: none)\n");
3169 ZERO_STRUCT(break_info
);
3170 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3171 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3172 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3173 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3174 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3175 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3176 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3178 torture_comment(tctx
, "setpathinfo attribute info should not trigger "
3179 "a break nor a violation\n");
3181 sfi
.generic
.level
= RAW_SFILEINFO_SETATTR
;
3182 sfi
.generic
.in
.file
.path
= fname
;
3183 sfi
.setattr
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
3184 sfi
.setattr
.in
.write_time
= 0;
3186 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
3187 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3189 torture_wait_for_oplock_break(tctx
);
3190 CHECK_VAL(break_info
.count
, 0);
3192 smbcli_close(cli1
->tree
, fnum
);
3195 smb_raw_exit(cli1
->session
);
3196 smb_raw_exit(cli2
->session
);
3197 smbcli_deltree(cli1
->tree
, BASEDIR
);
3202 * Similar to batch17/18, but test with open share mode rather than
3205 static bool test_raw_oplock_batch26(struct torture_context
*tctx
,
3206 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3208 const char *fname1
= BASEDIR
"\\test_batch26_1.dat";
3209 const char *fname2
= BASEDIR
"\\test_batch26_2.dat";
3213 union smb_rename rn
;
3216 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3221 smbcli_unlink(cli1
->tree
, fname1
);
3222 smbcli_unlink(cli1
->tree
, fname2
);
3224 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3228 base ntcreatex parms
3230 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3231 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3232 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3233 io
.ntcreatex
.in
.alloc_size
= 0;
3234 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3235 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3236 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
3237 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3238 io
.ntcreatex
.in
.create_options
= 0;
3239 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3240 io
.ntcreatex
.in
.security_flags
= 0;
3241 io
.ntcreatex
.in
.fname
= fname1
;
3243 torture_comment(tctx
, "BATCH26: open a file with an batch oplock "
3244 "(share mode: none)\n");
3246 ZERO_STRUCT(break_info
);
3247 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3248 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3249 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3252 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3253 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3254 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3255 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3257 torture_comment(tctx
, "rename should trigger a break\n");
3259 rn
.generic
.level
= RAW_RENAME_RENAME
;
3260 rn
.rename
.in
.pattern1
= fname1
;
3261 rn
.rename
.in
.pattern2
= fname2
;
3262 rn
.rename
.in
.attrib
= 0;
3264 torture_comment(tctx
, "trying rename while first file open\n");
3265 status
= smb_raw_rename(cli2
->tree
, &rn
);
3266 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3268 torture_wait_for_oplock_break(tctx
);
3269 CHECK_VAL(break_info
.count
, 1);
3270 CHECK_VAL(break_info
.failures
, 0);
3271 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3273 /* Close and reopen with batch again. */
3274 smbcli_close(cli1
->tree
, fnum
);
3275 ZERO_STRUCT(break_info
);
3277 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3278 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3279 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3280 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3282 /* Now try ntrename. */
3283 torture_comment(tctx
, "ntrename should trigger a break\n");
3285 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
3286 rn
.ntrename
.in
.attrib
= 0;
3287 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
3288 rn
.ntrename
.in
.old_name
= fname1
;
3289 rn
.ntrename
.in
.new_name
= fname2
;
3290 torture_comment(tctx
, "trying rename while first file open\n");
3291 status
= smb_raw_rename(cli2
->tree
, &rn
);
3292 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3294 torture_wait_for_oplock_break(tctx
);
3295 CHECK_VAL(break_info
.count
, 1);
3296 CHECK_VAL(break_info
.failures
, 0);
3297 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3299 smbcli_close(cli1
->tree
, fnum
);
3302 smb_raw_exit(cli1
->session
);
3303 smb_raw_exit(cli2
->session
);
3304 smbcli_deltree(cli1
->tree
, BASEDIR
);
3308 /* Test how oplocks work on streams. */
3309 static bool test_raw_oplock_stream1(struct torture_context
*tctx
,
3310 struct smbcli_state
*cli1
,
3311 struct smbcli_state
*cli2
)
3315 const char *fname_base
= BASEDIR
"\\test_stream1.txt";
3316 const char *stream
= "Stream One:$DATA";
3317 const char *fname_stream
, *fname_default_stream
;
3318 const char *default_stream
= "::$DATA";
3322 int stream_fnum
= -1;
3323 uint32_t batch_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3324 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
| NTCREATEX_FLAGS_EXTENDED
;
3325 uint32_t exclusive_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3326 NTCREATEX_FLAGS_EXTENDED
;
3328 #define NSTREAM_OPLOCK_RESULTS 8
3331 bool open_base_file
;
3332 uint32_t oplock_req
;
3333 uint32_t oplock_granted
;
3334 } stream_oplock_results
[NSTREAM_OPLOCK_RESULTS
] = {
3335 /* Request oplock on stream without the base file open. */
3336 {&fname_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3337 {&fname_default_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3338 {&fname_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3339 {&fname_default_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3341 /* Request oplock on stream with the base file open. */
3342 {&fname_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3343 {&fname_default_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3344 {&fname_stream
, true, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3345 {&fname_default_stream
, true, exclusive_req
, LEVEL_II_OPLOCK_RETURN
},
3350 /* Only passes against windows at the moment. */
3351 if (torture_setting_bool(tctx
, "samba3", false) ||
3352 torture_setting_bool(tctx
, "samba4", false)) {
3353 torture_skip(tctx
, "STREAM1 disabled against samba3+4\n");
3356 fname_stream
= talloc_asprintf(tctx
, "%s:%s", fname_base
, stream
);
3357 fname_default_stream
= talloc_asprintf(tctx
, "%s%s", fname_base
,
3360 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3363 smbcli_unlink(cli1
->tree
, fname_base
);
3365 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3366 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3368 /* Setup generic open parameters. */
3369 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3370 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3371 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
3372 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
3373 io
.ntcreatex
.in
.create_options
= 0;
3374 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3375 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3376 NTCREATEX_SHARE_ACCESS_WRITE
;
3377 io
.ntcreatex
.in
.alloc_size
= 0;
3378 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3379 io
.ntcreatex
.in
.security_flags
= 0;
3381 /* Create the file with a stream */
3382 io
.ntcreatex
.in
.fname
= fname_stream
;
3383 io
.ntcreatex
.in
.flags
= 0;
3384 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
3385 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3386 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3387 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3389 /* Change the disposition to open now that the file has been created. */
3390 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3392 /* Try some permutations of taking oplocks on streams. */
3393 for (i
= 0; i
< NSTREAM_OPLOCK_RESULTS
; i
++) {
3394 const char *fname
= *stream_oplock_results
[i
].fname
;
3395 bool open_base_file
= stream_oplock_results
[i
].open_base_file
;
3396 uint32_t oplock_req
= stream_oplock_results
[i
].oplock_req
;
3397 uint32_t oplock_granted
=
3398 stream_oplock_results
[i
].oplock_granted
;
3401 if (open_base_file
) {
3402 torture_comment(tctx
, "Opening base file: %s with "
3403 "%d\n", fname_base
, batch_req
);
3404 io
.ntcreatex
.in
.fname
= fname_base
;
3405 io
.ntcreatex
.in
.flags
= batch_req
;
3406 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3407 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3408 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3409 BATCH_OPLOCK_RETURN
);
3410 base_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3413 torture_comment(tctx
, "%d: Opening stream: %s with %d\n", i
,
3415 io
.ntcreatex
.in
.fname
= fname
;
3416 io
.ntcreatex
.in
.flags
= oplock_req
;
3418 /* Do the open with the desired oplock on the stream. */
3419 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3420 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3421 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, oplock_granted
);
3422 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3424 /* Cleanup the base file if it was opened. */
3425 if (base_fnum
!= -1) {
3426 smbcli_close(cli2
->tree
, base_fnum
);
3430 /* Open the stream with an exclusive oplock. */
3431 torture_comment(tctx
, "Opening stream: %s with %d\n",
3432 fname_stream
, exclusive_req
);
3433 io
.ntcreatex
.in
.fname
= fname_stream
;
3434 io
.ntcreatex
.in
.flags
= exclusive_req
;
3435 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3436 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3437 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3438 stream_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3440 /* Open the base file and see if it contends. */
3441 ZERO_STRUCT(break_info
);
3442 torture_comment(tctx
, "Opening base file: %s with "
3443 "%d\n", fname_base
, batch_req
);
3444 io
.ntcreatex
.in
.fname
= fname_base
;
3445 io
.ntcreatex
.in
.flags
= batch_req
;
3446 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3447 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3448 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3449 BATCH_OPLOCK_RETURN
);
3450 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3452 torture_wait_for_oplock_break(tctx
);
3453 CHECK_VAL(break_info
.count
, 0);
3454 CHECK_VAL(break_info
.failures
, 0);
3456 /* Open the stream again to see if it contends. */
3457 ZERO_STRUCT(break_info
);
3458 torture_comment(tctx
, "Opening stream again: %s with "
3459 "%d\n", fname_base
, batch_req
);
3460 io
.ntcreatex
.in
.fname
= fname_stream
;
3461 io
.ntcreatex
.in
.flags
= exclusive_req
;
3462 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3463 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3464 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3465 LEVEL_II_OPLOCK_RETURN
);
3466 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3468 torture_wait_for_oplock_break(tctx
);
3469 CHECK_VAL(break_info
.count
, 1);
3470 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3471 CHECK_VAL(break_info
.failures
, 0);
3473 /* Close the stream. */
3474 if (stream_fnum
!= -1) {
3475 smbcli_close(cli1
->tree
, stream_fnum
);
3479 smbcli_close(cli1
->tree
, fnum
);
3480 smb_raw_exit(cli1
->session
);
3481 smb_raw_exit(cli2
->session
);
3482 smbcli_deltree(cli1
->tree
, BASEDIR
);
3486 static bool test_raw_oplock_doc(struct torture_context
*tctx
,
3487 struct smbcli_state
*cli
)
3489 const char *fname
= BASEDIR
"\\test_oplock_doc.dat";
3495 if (!torture_setup_dir(cli
, BASEDIR
)) {
3500 smbcli_unlink(cli
->tree
, fname
);
3502 smbcli_oplock_handler(cli
->transport
, oplock_handler_ack_to_given
,
3506 base ntcreatex parms
3508 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3509 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3510 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3511 io
.ntcreatex
.in
.alloc_size
= 0;
3512 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3513 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3514 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3515 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
3516 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3517 io
.ntcreatex
.in
.security_flags
= 0;
3518 io
.ntcreatex
.in
.fname
= fname
;
3520 torture_comment(tctx
, "open a delete-on-close file with a batch "
3522 ZERO_STRUCT(break_info
);
3523 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3524 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3525 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3527 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
3528 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3529 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3530 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3532 smbcli_close(cli
->tree
, fnum
);
3535 smb_raw_exit(cli
->session
);
3536 smbcli_deltree(cli
->tree
, BASEDIR
);
3540 /* Open a file with a batch oplock, then open it again from a second client
3541 * requesting no oplock. Having two open file handles should break our own
3542 * oplock during BRL acquisition.
3544 static bool test_raw_oplock_brl1(struct torture_context
*tctx
,
3545 struct smbcli_state
*cli1
,
3546 struct smbcli_state
*cli2
)
3548 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3552 bool correct
= true;
3558 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3563 smbcli_unlink(cli1
->tree
, fname
);
3565 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3569 base ntcreatex parms
3571 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3572 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3573 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3574 SEC_RIGHTS_FILE_WRITE
;
3575 io
.ntcreatex
.in
.alloc_size
= 0;
3576 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3577 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3578 NTCREATEX_SHARE_ACCESS_WRITE
;
3579 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3580 io
.ntcreatex
.in
.create_options
= 0;
3581 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3582 io
.ntcreatex
.in
.security_flags
= 0;
3583 io
.ntcreatex
.in
.fname
= fname
;
3586 with a batch oplock we get a break
3588 torture_comment(tctx
, "open with batch oplock\n");
3589 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3590 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3591 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3593 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3594 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3595 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3596 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3597 /* create a file with bogus data */
3598 memset(buf
, 0, sizeof(buf
));
3600 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3603 torture_comment(tctx
, "Failed to create file\n");
3608 torture_comment(tctx
, "a 2nd open should give a break\n");
3609 ZERO_STRUCT(break_info
);
3611 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3612 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3613 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3614 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3615 CHECK_VAL(break_info
.count
, 1);
3616 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3617 CHECK_VAL(break_info
.failures
, 0);
3618 CHECK_VAL(break_info
.fnum
, fnum
);
3620 ZERO_STRUCT(break_info
);
3622 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3624 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3625 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3627 torture_wait_for_oplock_break(tctx
);
3628 CHECK_VAL(break_info
.count
, 1);
3629 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3630 CHECK_VAL(break_info
.fnum
, fnum
);
3631 CHECK_VAL(break_info
.failures
, 0);
3633 /* expect no oplock break */
3634 ZERO_STRUCT(break_info
);
3635 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3636 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3638 torture_wait_for_oplock_break(tctx
);
3639 CHECK_VAL(break_info
.count
, 0);
3640 CHECK_VAL(break_info
.level
, 0);
3641 CHECK_VAL(break_info
.fnum
, 0);
3642 CHECK_VAL(break_info
.failures
, 0);
3644 smbcli_close(cli1
->tree
, fnum
);
3645 smbcli_close(cli2
->tree
, fnum2
);
3648 smb_raw_exit(cli1
->session
);
3649 smb_raw_exit(cli2
->session
);
3650 smbcli_deltree(cli1
->tree
, BASEDIR
);
3655 /* Open a file with a batch oplock on one client and then acquire a brl.
3656 * We should not contend our own oplock.
3658 static bool test_raw_oplock_brl2(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
3660 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3664 bool correct
= true;
3669 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3674 smbcli_unlink(cli1
->tree
, fname
);
3676 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3680 base ntcreatex parms
3682 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3683 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3684 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3685 SEC_RIGHTS_FILE_WRITE
;
3686 io
.ntcreatex
.in
.alloc_size
= 0;
3687 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3688 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3689 NTCREATEX_SHARE_ACCESS_WRITE
;
3690 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3691 io
.ntcreatex
.in
.create_options
= 0;
3692 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3693 io
.ntcreatex
.in
.security_flags
= 0;
3694 io
.ntcreatex
.in
.fname
= fname
;
3697 with a batch oplock we get a break
3699 torture_comment(tctx
, "open with batch oplock\n");
3700 ZERO_STRUCT(break_info
);
3701 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3702 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3703 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3705 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3706 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3707 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3708 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3710 /* create a file with bogus data */
3711 memset(buf
, 0, sizeof(buf
));
3713 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3716 torture_comment(tctx
, "Failed to create file\n");
3721 torture_comment(tctx
, "a self BRL acquisition should not break to "
3724 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3725 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3727 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3728 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3730 /* With one file handle open a BRL should not contend our oplock.
3731 * Thus, no oplock break will be received and the entire break_info
3732 * struct will be 0 */
3733 torture_wait_for_oplock_break(tctx
);
3734 CHECK_VAL(break_info
.fnum
, 0);
3735 CHECK_VAL(break_info
.count
, 0);
3736 CHECK_VAL(break_info
.level
, 0);
3737 CHECK_VAL(break_info
.failures
, 0);
3739 smbcli_close(cli1
->tree
, fnum
);
3742 smb_raw_exit(cli1
->session
);
3743 smbcli_deltree(cli1
->tree
, BASEDIR
);
3747 /* Open a file with a batch oplock twice from one client and then acquire a
3748 * brl. BRL acquisition should break our own oplock.
3750 static bool test_raw_oplock_brl3(struct torture_context
*tctx
,
3751 struct smbcli_state
*cli1
)
3753 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3756 bool correct
= true;
3762 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3767 smbcli_unlink(cli1
->tree
, fname
);
3769 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3773 base ntcreatex parms
3775 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3776 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3777 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3778 SEC_RIGHTS_FILE_WRITE
;
3779 io
.ntcreatex
.in
.alloc_size
= 0;
3780 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3781 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3782 NTCREATEX_SHARE_ACCESS_WRITE
;
3783 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3784 io
.ntcreatex
.in
.create_options
= 0;
3785 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3786 io
.ntcreatex
.in
.security_flags
= 0;
3787 io
.ntcreatex
.in
.fname
= fname
;
3790 with a batch oplock we get a break
3792 torture_comment(tctx
, "open with batch oplock\n");
3793 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3794 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3795 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3797 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3798 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3799 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3800 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3802 /* create a file with bogus data */
3803 memset(buf
, 0, sizeof(buf
));
3805 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3808 torture_comment(tctx
, "Failed to create file\n");
3813 torture_comment(tctx
, "a 2nd open should give a break\n");
3814 ZERO_STRUCT(break_info
);
3816 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3817 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3818 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3819 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3820 CHECK_VAL(break_info
.count
, 1);
3821 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3822 CHECK_VAL(break_info
.failures
, 0);
3823 CHECK_VAL(break_info
.fnum
, fnum
);
3825 ZERO_STRUCT(break_info
);
3827 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3829 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3830 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3832 torture_wait_for_oplock_break(tctx
);
3833 CHECK_VAL(break_info
.count
, 1);
3834 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3835 CHECK_VAL(break_info
.fnum
, fnum
);
3836 CHECK_VAL(break_info
.failures
, 0);
3838 /* expect no oplock break */
3839 ZERO_STRUCT(break_info
);
3840 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3841 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3843 torture_wait_for_oplock_break(tctx
);
3844 CHECK_VAL(break_info
.count
, 0);
3845 CHECK_VAL(break_info
.level
, 0);
3846 CHECK_VAL(break_info
.fnum
, 0);
3847 CHECK_VAL(break_info
.failures
, 0);
3849 smbcli_close(cli1
->tree
, fnum
);
3850 smbcli_close(cli1
->tree
, fnum2
);
3853 smb_raw_exit(cli1
->session
);
3854 smbcli_deltree(cli1
->tree
, BASEDIR
);
3859 * Open a file with an exclusive oplock from the 1st client and acquire a
3860 * brl. Then open the same file from the 2nd client that should give oplock
3861 * break with level2 to the 1st and return no oplock to the 2nd.
3863 static bool test_raw_oplock_brl4(struct torture_context
*tctx
,
3864 struct smbcli_state
*cli1
,
3865 struct smbcli_state
*cli2
)
3867 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3870 bool correct
= true;
3876 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3881 smbcli_unlink(cli1
->tree
, fname
);
3883 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3887 base ntcreatex parms
3889 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3890 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3891 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3892 SEC_RIGHTS_FILE_WRITE
;
3893 io
.ntcreatex
.in
.alloc_size
= 0;
3894 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3895 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3896 NTCREATEX_SHARE_ACCESS_WRITE
;
3897 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3898 io
.ntcreatex
.in
.create_options
= 0;
3899 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3900 io
.ntcreatex
.in
.security_flags
= 0;
3901 io
.ntcreatex
.in
.fname
= fname
;
3903 torture_comment(tctx
, "open with exclusive oplock\n");
3904 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3905 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
3907 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3909 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3910 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3911 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3913 /* create a file with bogus data */
3914 memset(buf
, 0, sizeof(buf
));
3916 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3919 torture_comment(tctx
, "Failed to create file\n");
3924 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 1, 0, WRITE_LOCK
);
3925 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3927 torture_comment(tctx
, "a 2nd open should give a break to the 1st\n");
3928 ZERO_STRUCT(break_info
);
3930 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3932 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3933 CHECK_VAL(break_info
.count
, 1);
3934 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3935 CHECK_VAL(break_info
.failures
, 0);
3936 CHECK_VAL(break_info
.fnum
, fnum
);
3938 torture_comment(tctx
, "and return no oplock to the 2nd\n");
3939 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3940 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3942 smbcli_close(cli1
->tree
, fnum
);
3943 smbcli_close(cli2
->tree
, fnum2
);
3946 smb_raw_exit(cli1
->session
);
3947 smb_raw_exit(cli2
->session
);
3948 smbcli_deltree(cli1
->tree
, BASEDIR
);
3953 basic testing of oplocks
3955 struct torture_suite
*torture_raw_oplock(TALLOC_CTX
*mem_ctx
)
3957 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "oplock");
3959 torture_suite_add_2smb_test(suite
, "exclusive1", test_raw_oplock_exclusive1
);
3960 torture_suite_add_2smb_test(suite
, "exclusive2", test_raw_oplock_exclusive2
);
3961 torture_suite_add_2smb_test(suite
, "exclusive3", test_raw_oplock_exclusive3
);
3962 torture_suite_add_2smb_test(suite
, "exclusive4", test_raw_oplock_exclusive4
);
3963 torture_suite_add_2smb_test(suite
, "exclusive5", test_raw_oplock_exclusive5
);
3964 torture_suite_add_2smb_test(suite
, "exclusive6", test_raw_oplock_exclusive6
);
3965 torture_suite_add_2smb_test(suite
, "exclusive7", test_raw_oplock_exclusive7
);
3966 torture_suite_add_2smb_test(suite
, "batch1", test_raw_oplock_batch1
);
3967 torture_suite_add_2smb_test(suite
, "batch2", test_raw_oplock_batch2
);
3968 torture_suite_add_2smb_test(suite
, "batch3", test_raw_oplock_batch3
);
3969 torture_suite_add_2smb_test(suite
, "batch4", test_raw_oplock_batch4
);
3970 torture_suite_add_2smb_test(suite
, "batch5", test_raw_oplock_batch5
);
3971 torture_suite_add_2smb_test(suite
, "batch6", test_raw_oplock_batch6
);
3972 torture_suite_add_2smb_test(suite
, "batch7", test_raw_oplock_batch7
);
3973 torture_suite_add_2smb_test(suite
, "batch8", test_raw_oplock_batch8
);
3974 torture_suite_add_2smb_test(suite
, "batch9", test_raw_oplock_batch9
);
3975 torture_suite_add_2smb_test(suite
, "batch10", test_raw_oplock_batch10
);
3976 torture_suite_add_2smb_test(suite
, "batch11", test_raw_oplock_batch11
);
3977 torture_suite_add_2smb_test(suite
, "batch12", test_raw_oplock_batch12
);
3978 torture_suite_add_2smb_test(suite
, "batch13", test_raw_oplock_batch13
);
3979 torture_suite_add_2smb_test(suite
, "batch14", test_raw_oplock_batch14
);
3980 torture_suite_add_2smb_test(suite
, "batch15", test_raw_oplock_batch15
);
3981 torture_suite_add_2smb_test(suite
, "batch16", test_raw_oplock_batch16
);
3982 torture_suite_add_2smb_test(suite
, "batch17", test_raw_oplock_batch17
);
3983 torture_suite_add_2smb_test(suite
, "batch18", test_raw_oplock_batch18
);
3984 torture_suite_add_2smb_test(suite
, "batch19", test_raw_oplock_batch19
);
3985 torture_suite_add_2smb_test(suite
, "batch20", test_raw_oplock_batch20
);
3986 torture_suite_add_2smb_test(suite
, "batch21", test_raw_oplock_batch21
);
3987 torture_suite_add_2smb_test(suite
, "batch22", test_raw_oplock_batch22
);
3988 torture_suite_add_2smb_test(suite
, "batch23", test_raw_oplock_batch23
);
3989 torture_suite_add_2smb_test(suite
, "batch24", test_raw_oplock_batch24
);
3990 torture_suite_add_2smb_test(suite
, "batch25", test_raw_oplock_batch25
);
3991 torture_suite_add_2smb_test(suite
, "batch26", test_raw_oplock_batch26
);
3992 torture_suite_add_2smb_test(suite
, "stream1", test_raw_oplock_stream1
);
3993 torture_suite_add_1smb_test(suite
, "doc1", test_raw_oplock_doc
);
3994 torture_suite_add_2smb_test(suite
, "brl1", test_raw_oplock_brl1
);
3995 torture_suite_add_1smb_test(suite
, "brl2", test_raw_oplock_brl2
);
3996 torture_suite_add_1smb_test(suite
, "brl3", test_raw_oplock_brl3
);
3997 torture_suite_add_2smb_test(suite
, "brl4", test_raw_oplock_brl4
);
4003 stress testing of oplocks
4005 bool torture_bench_oplock(struct torture_context
*torture
)
4007 struct smbcli_state
**cli
;
4009 TALLOC_CTX
*mem_ctx
= talloc_new(torture
);
4010 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
4012 int timelimit
= torture_setting_int(torture
, "timelimit", 10);
4016 cli
= talloc_array(mem_ctx
, struct smbcli_state
*, torture_nprocs
);
4018 torture_comment(torture
, "Opening %d connections\n", torture_nprocs
);
4019 for (i
=0;i
<torture_nprocs
;i
++) {
4020 if (!torture_open_connection_ev(&cli
[i
], i
, torture
, torture
->ev
)) {
4023 talloc_steal(mem_ctx
, cli
[i
]);
4024 smbcli_oplock_handler(cli
[i
]->transport
, oplock_handler_close
,
4028 if (!torture_setup_dir(cli
[0], BASEDIR
)) {
4033 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
4034 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4035 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4036 io
.ntcreatex
.in
.alloc_size
= 0;
4037 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4038 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
4039 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4040 io
.ntcreatex
.in
.create_options
= 0;
4041 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4042 io
.ntcreatex
.in
.security_flags
= 0;
4043 io
.ntcreatex
.in
.fname
= BASEDIR
"\\test.dat";
4044 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4045 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4046 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4048 tv
= timeval_current();
4051 we open the same file with SHARE_ACCESS_NONE from all the
4052 connections in a round robin fashion. Each open causes an
4053 oplock break on the previous connection, which is answered
4054 by the oplock_handler_close() to close the file.
4056 This measures how fast we can pass on oplocks, and stresses
4057 the oplock handling code
4059 torture_comment(torture
, "Running for %d seconds\n", timelimit
);
4060 while (timeval_elapsed(&tv
) < timelimit
) {
4061 for (i
=0;i
<torture_nprocs
;i
++) {
4064 status
= smb_raw_open(cli
[i
]->tree
, mem_ctx
, &io
);
4065 CHECK_STATUS(torture
, status
, NT_STATUS_OK
);
4069 if (torture_setting_bool(torture
, "progress", true)) {
4070 torture_comment(torture
, "%.2f ops/second\r", count
/timeval_elapsed(&tv
));
4074 torture_comment(torture
, "%.2f ops/second\n", count
/timeval_elapsed(&tv
));
4076 smb_raw_exit(cli
[torture_nprocs
-1]->session
);
4079 smb_raw_exit(cli
[0]->session
);
4080 smbcli_deltree(cli
[0]->tree
, BASEDIR
);
4081 talloc_free(mem_ctx
);
4086 static struct hold_oplock_info
{
4088 bool close_on_break
;
4089 uint32_t share_access
;
4092 { BASEDIR
"\\notshared_close", true,
4093 NTCREATEX_SHARE_ACCESS_NONE
, },
4094 { BASEDIR
"\\notshared_noclose", false,
4095 NTCREATEX_SHARE_ACCESS_NONE
, },
4096 { BASEDIR
"\\shared_close", true,
4097 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4098 { BASEDIR
"\\shared_noclose", false,
4099 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4102 static bool oplock_handler_hold(struct smbcli_transport
*transport
,
4103 uint16_t tid
, uint16_t fnum
, uint8_t level
,
4106 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
4107 struct hold_oplock_info
*info
;
4110 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4111 if (hold_info
[i
].fnum
== fnum
) break;
4114 if (i
== ARRAY_SIZE(hold_info
)) {
4115 printf("oplock break for unknown fnum %u\n", fnum
);
4119 info
= &hold_info
[i
];
4121 if (info
->close_on_break
) {
4122 printf("oplock break on %s - closing\n",
4124 oplock_handler_close(transport
, tid
, fnum
, level
, private_data
);
4128 printf("oplock break on %s - acking break\n", info
->fname
);
4130 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
4135 used for manual testing of oplocks - especially interaction with
4136 other filesystems (such as NFS and local access)
4138 bool torture_hold_oplock(struct torture_context
*torture
,
4139 struct smbcli_state
*cli
)
4141 struct tevent_context
*ev
=
4142 (struct tevent_context
*)cli
->transport
->socket
->event
.ctx
;
4145 printf("Setting up open files with oplocks in %s\n", BASEDIR
);
4147 if (!torture_setup_dir(cli
, BASEDIR
)) {
4151 smbcli_oplock_handler(cli
->transport
, oplock_handler_hold
, cli
->tree
);
4153 /* setup the files */
4154 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4159 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4160 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4161 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4162 io
.ntcreatex
.in
.alloc_size
= 0;
4163 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4164 io
.ntcreatex
.in
.share_access
= hold_info
[i
].share_access
;
4165 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4166 io
.ntcreatex
.in
.create_options
= 0;
4167 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4168 io
.ntcreatex
.in
.security_flags
= 0;
4169 io
.ntcreatex
.in
.fname
= hold_info
[i
].fname
;
4170 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4171 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4172 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4173 printf("opening %s\n", hold_info
[i
].fname
);
4175 status
= smb_raw_open(cli
->tree
, cli
, &io
);
4176 if (!NT_STATUS_IS_OK(status
)) {
4177 printf("Failed to open %s - %s\n",
4178 hold_info
[i
].fname
, nt_errstr(status
));
4182 if (io
.ntcreatex
.out
.oplock_level
!= BATCH_OPLOCK_RETURN
) {
4183 printf("Oplock not granted for %s - expected %d but got %d\n",
4184 hold_info
[i
].fname
, BATCH_OPLOCK_RETURN
,
4185 io
.ntcreatex
.out
.oplock_level
);
4188 hold_info
[i
].fnum
= io
.ntcreatex
.out
.file
.fnum
;
4190 /* make the file non-zero size */
4191 if (smbcli_write(cli
->tree
, hold_info
[i
].fnum
, 0, &c
, 0, 1) != 1) {
4192 printf("Failed to write to file\n");
4197 printf("Waiting for oplock events\n");
4198 event_loop_wait(ev
);