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"
29 #include "torture/raw/proto.h"
31 #define CHECK_VAL(v, correct) do { \
32 if ((v) != (correct)) { \
33 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got 0x%x - should be 0x%x\n", \
34 __location__, #v, (int)v, (int)correct); \
38 #define CHECK_RANGE(v, min, max) do { \
39 if ((v) < (min) || (v) > (max)) { \
40 torture_warning(tctx, "(%s): wrong value for %s got " \
41 "%d - should be between %d and %d\n", \
42 __location__, #v, (int)v, (int)min, (int)max); \
45 #define CHECK_STRMATCH(v, correct) do { \
46 if (!v || strstr((v),(correct)) == NULL) { \
47 torture_result(tctx, TORTURE_FAIL, "(%s): wrong value for %s got '%s' - should be '%s'\n", \
48 __location__, #v, v?v:"NULL", correct); \
53 #define CHECK_STATUS(tctx, status, correct) do { \
54 if (!NT_STATUS_EQUAL(status, correct)) { \
55 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
56 nt_errstr(status), nt_errstr(correct)); \
69 #define BASEDIR "\\test_oplock"
72 a handler function for oplock break requests. Ack it as a break to level II if possible
74 static bool oplock_handler_ack_to_given(struct smbcli_transport
*transport
,
75 uint16_t tid
, uint16_t fnum
,
76 uint8_t level
, void *private_data
)
78 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
81 break_info
.fnum
= fnum
;
82 break_info
.level
= level
;
86 case OPLOCK_BREAK_TO_LEVEL_II
:
89 case OPLOCK_BREAK_TO_NONE
:
94 break_info
.failures
++;
96 printf("Acking to %s [0x%02X] in oplock handler\n",
99 return smbcli_oplock_ack(tree
, fnum
, level
);
103 a handler function for oplock break requests. Ack it as a break to none
105 static bool oplock_handler_ack_to_none(struct smbcli_transport
*transport
,
106 uint16_t tid
, uint16_t fnum
,
107 uint8_t level
, void *private_data
)
109 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
110 break_info
.fnum
= fnum
;
111 break_info
.level
= level
;
114 printf("Acking to none in oplock handler\n");
116 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
120 a handler function for oplock break requests. Let it timeout
122 static bool oplock_handler_timeout(struct smbcli_transport
*transport
,
123 uint16_t tid
, uint16_t fnum
,
124 uint8_t level
, void *private_data
)
126 break_info
.fnum
= fnum
;
127 break_info
.level
= level
;
130 printf("Let oplock break timeout\n");
134 static void oplock_handler_close_recv(struct smbcli_request
*req
)
137 status
= smbcli_request_simple_recv(req
);
138 if (!NT_STATUS_IS_OK(status
)) {
139 printf("close failed in oplock_handler_close\n");
140 break_info
.failures
++;
145 a handler function for oplock break requests - close the file
147 static bool oplock_handler_close(struct smbcli_transport
*transport
, uint16_t tid
,
148 uint16_t fnum
, uint8_t level
, void *private_data
)
151 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
152 struct smbcli_request
*req
;
154 break_info
.fnum
= fnum
;
155 break_info
.level
= level
;
158 io
.close
.level
= RAW_CLOSE_CLOSE
;
159 io
.close
.in
.file
.fnum
= fnum
;
160 io
.close
.in
.write_time
= 0;
161 req
= smb_raw_close_send(tree
, &io
);
163 printf("failed to send close in oplock_handler_close\n");
167 req
->async
.fn
= oplock_handler_close_recv
;
168 req
->async
.private_data
= NULL
;
173 static bool open_connection_no_level2_oplocks(struct torture_context
*tctx
,
174 struct smbcli_state
**c
)
177 struct smbcli_options options
;
178 struct smbcli_session_options session_options
;
180 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
181 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &session_options
);
183 options
.use_level2_oplocks
= false;
185 status
= smbcli_full_connection(tctx
, c
,
186 torture_setting_string(tctx
, "host", NULL
),
187 lpcfg_smb_ports(tctx
->lp_ctx
),
188 torture_setting_string(tctx
, "share", NULL
),
189 NULL
, lpcfg_socket_options(tctx
->lp_ctx
), cmdline_credentials
,
190 lpcfg_resolve_context(tctx
->lp_ctx
),
191 tctx
->ev
, &options
, &session_options
,
192 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
193 if (!NT_STATUS_IS_OK(status
)) {
194 torture_comment(tctx
, "Failed to open connection - %s\n",
203 Timer handler function notifies the registering function that time is up
205 static void timeout_cb(struct tevent_context
*ev
,
206 struct tevent_timer
*te
,
207 struct timeval current_time
,
210 bool *timesup
= (bool *)private_data
;
216 Wait a short period of time to receive a single oplock break request
218 static void torture_wait_for_oplock_break(struct torture_context
*tctx
)
220 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
221 struct tevent_timer
*te
= NULL
;
223 bool timesup
= false;
224 int old_count
= break_info
.count
;
226 /* Wait .1 seconds for an oplock break */
227 ne
= tevent_timeval_current_ofs(0, 100000);
229 if ((te
= tevent_add_timer(tctx
->ev
, tmp_ctx
, ne
, timeout_cb
, ×up
))
232 torture_comment(tctx
, "Failed to wait for an oplock break. "
233 "test results may not be accurate.");
237 while (!timesup
&& break_info
.count
< old_count
+ 1) {
238 if (tevent_loop_once(tctx
->ev
) != 0) {
239 torture_comment(tctx
, "Failed to wait for an oplock "
240 "break. test results may not be "
247 /* We don't know if the timed event fired and was freed, we received
248 * our oplock break, or some other event triggered the loop. Thus,
249 * we create a tmp_ctx to be able to safely free/remove the timed
250 * event in all 3 cases. */
251 talloc_free(tmp_ctx
);
256 static uint8_t get_break_level1_to_none_count(struct torture_context
*tctx
)
258 return torture_setting_bool(tctx
, "2_step_break_to_none", false) ?
262 static bool test_raw_oplock_exclusive1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
264 const char *fname
= BASEDIR
"\\test_exclusive1.dat";
268 union smb_unlink unl
;
271 if (!torture_setup_dir(cli1
, BASEDIR
)) {
276 smbcli_unlink(cli1
->tree
, fname
);
278 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
283 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
284 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
285 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
286 io
.ntcreatex
.in
.alloc_size
= 0;
287 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
288 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
289 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
290 io
.ntcreatex
.in
.create_options
= 0;
291 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
292 io
.ntcreatex
.in
.security_flags
= 0;
293 io
.ntcreatex
.in
.fname
= fname
;
295 torture_comment(tctx
, "EXCLUSIVE1: open a file with an exclusive oplock (share mode: none)\n");
296 ZERO_STRUCT(break_info
);
297 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
299 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
300 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
301 fnum
= io
.ntcreatex
.out
.file
.fnum
;
302 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
304 torture_comment(tctx
, "a 2nd open should not cause a break\n");
305 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
306 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
307 torture_wait_for_oplock_break(tctx
);
308 CHECK_VAL(break_info
.count
, 0);
309 CHECK_VAL(break_info
.failures
, 0);
311 torture_comment(tctx
, "unlink it - should also be no break\n");
312 unl
.unlink
.in
.pattern
= fname
;
313 unl
.unlink
.in
.attrib
= 0;
314 status
= smb_raw_unlink(cli2
->tree
, &unl
);
315 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
316 torture_wait_for_oplock_break(tctx
);
317 CHECK_VAL(break_info
.count
, 0);
318 CHECK_VAL(break_info
.failures
, 0);
320 smbcli_close(cli1
->tree
, fnum
);
323 smb_raw_exit(cli1
->session
);
324 smb_raw_exit(cli2
->session
);
325 smbcli_deltree(cli1
->tree
, BASEDIR
);
329 static bool test_raw_oplock_exclusive2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
331 const char *fname
= BASEDIR
"\\test_exclusive2.dat";
335 union smb_unlink unl
;
336 uint16_t fnum
=0, fnum2
=0;
338 if (!torture_setup_dir(cli1
, BASEDIR
)) {
343 smbcli_unlink(cli1
->tree
, fname
);
345 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
350 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
351 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
352 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
353 io
.ntcreatex
.in
.alloc_size
= 0;
354 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
355 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
356 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
357 io
.ntcreatex
.in
.create_options
= 0;
358 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
359 io
.ntcreatex
.in
.security_flags
= 0;
360 io
.ntcreatex
.in
.fname
= fname
;
362 torture_comment(tctx
, "EXCLUSIVE2: open a file with an exclusive oplock (share mode: all)\n");
363 ZERO_STRUCT(break_info
);
364 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
365 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
366 NTCREATEX_SHARE_ACCESS_WRITE
|
367 NTCREATEX_SHARE_ACCESS_DELETE
;
369 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
370 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
371 fnum
= io
.ntcreatex
.out
.file
.fnum
;
372 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
374 torture_comment(tctx
, "a 2nd open should cause a break to level 2\n");
375 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
376 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
377 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
378 torture_wait_for_oplock_break(tctx
);
379 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
380 CHECK_VAL(break_info
.count
, 1);
381 CHECK_VAL(break_info
.fnum
, fnum
);
382 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
383 CHECK_VAL(break_info
.failures
, 0);
384 ZERO_STRUCT(break_info
);
386 /* now we have 2 level II oplocks... */
387 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
388 unl
.unlink
.in
.pattern
= fname
;
389 unl
.unlink
.in
.attrib
= 0;
390 status
= smb_raw_unlink(cli2
->tree
, &unl
);
391 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
392 torture_wait_for_oplock_break(tctx
);
393 CHECK_VAL(break_info
.count
, 0);
394 CHECK_VAL(break_info
.failures
, 0);
396 torture_comment(tctx
, "close 1st handle\n");
397 smbcli_close(cli1
->tree
, fnum
);
399 torture_comment(tctx
, "try to unlink it - should not cause a break, but a sharing violation\n");
400 unl
.unlink
.in
.pattern
= fname
;
401 unl
.unlink
.in
.attrib
= 0;
402 status
= smb_raw_unlink(cli2
->tree
, &unl
);
403 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
404 torture_wait_for_oplock_break(tctx
);
405 CHECK_VAL(break_info
.count
, 0);
406 CHECK_VAL(break_info
.failures
, 0);
408 torture_comment(tctx
, "close 2nd handle\n");
409 smbcli_close(cli2
->tree
, fnum2
);
411 torture_comment(tctx
, "unlink it\n");
412 unl
.unlink
.in
.pattern
= fname
;
413 unl
.unlink
.in
.attrib
= 0;
414 status
= smb_raw_unlink(cli2
->tree
, &unl
);
415 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
416 torture_wait_for_oplock_break(tctx
);
417 CHECK_VAL(break_info
.count
, 0);
418 CHECK_VAL(break_info
.failures
, 0);
421 smb_raw_exit(cli1
->session
);
422 smb_raw_exit(cli2
->session
);
423 smbcli_deltree(cli1
->tree
, BASEDIR
);
427 static bool test_raw_oplock_exclusive3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
429 const char *fname
= BASEDIR
"\\test_exclusive3.dat";
433 union smb_setfileinfo sfi
;
436 if (!torture_setup_dir(cli1
, BASEDIR
)) {
441 smbcli_unlink(cli1
->tree
, fname
);
443 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
448 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
449 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
450 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
451 io
.ntcreatex
.in
.alloc_size
= 0;
452 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
453 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
454 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
455 io
.ntcreatex
.in
.create_options
= 0;
456 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
457 io
.ntcreatex
.in
.security_flags
= 0;
458 io
.ntcreatex
.in
.fname
= fname
;
460 torture_comment(tctx
, "EXCLUSIVE3: open a file with an exclusive oplock (share mode: none)\n");
462 ZERO_STRUCT(break_info
);
463 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
465 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
466 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
467 fnum
= io
.ntcreatex
.out
.file
.fnum
;
468 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
470 torture_comment(tctx
, "setpathinfo EOF should trigger a break to none\n");
472 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
473 sfi
.generic
.in
.file
.path
= fname
;
474 sfi
.end_of_file_info
.in
.size
= 100;
476 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
478 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
479 torture_wait_for_oplock_break(tctx
);
480 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
481 CHECK_VAL(break_info
.failures
, 0);
482 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
484 smbcli_close(cli1
->tree
, fnum
);
487 smb_raw_exit(cli1
->session
);
488 smb_raw_exit(cli2
->session
);
489 smbcli_deltree(cli1
->tree
, BASEDIR
);
493 static bool test_raw_oplock_exclusive4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
495 const char *fname
= BASEDIR
"\\test_exclusive4.dat";
499 uint16_t fnum
=0, fnum2
=0;
501 if (!torture_setup_dir(cli1
, BASEDIR
)) {
506 smbcli_unlink(cli1
->tree
, fname
);
508 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
513 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
514 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
515 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
516 io
.ntcreatex
.in
.alloc_size
= 0;
517 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
518 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
519 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
520 io
.ntcreatex
.in
.create_options
= 0;
521 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
522 io
.ntcreatex
.in
.security_flags
= 0;
523 io
.ntcreatex
.in
.fname
= fname
;
525 torture_comment(tctx
, "EXCLUSIVE4: open with exclusive oplock\n");
526 ZERO_STRUCT(break_info
);
527 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
529 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
530 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
531 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
532 fnum
= io
.ntcreatex
.out
.file
.fnum
;
533 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
535 ZERO_STRUCT(break_info
);
536 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
538 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
539 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
540 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
541 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
542 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
543 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
544 torture_wait_for_oplock_break(tctx
);
545 CHECK_VAL(break_info
.count
, 0);
546 CHECK_VAL(break_info
.failures
, 0);
548 smbcli_close(cli1
->tree
, fnum
);
549 smbcli_close(cli2
->tree
, fnum2
);
552 smb_raw_exit(cli1
->session
);
553 smb_raw_exit(cli2
->session
);
554 smbcli_deltree(cli1
->tree
, BASEDIR
);
558 static bool test_raw_oplock_exclusive5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
560 const char *fname
= BASEDIR
"\\test_exclusive5.dat";
564 uint16_t fnum
=0, fnum2
=0;
566 if (!torture_setup_dir(cli1
, BASEDIR
)) {
571 smbcli_unlink(cli1
->tree
, fname
);
573 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
574 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
579 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
580 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
581 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
582 io
.ntcreatex
.in
.alloc_size
= 0;
583 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
584 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
585 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
586 io
.ntcreatex
.in
.create_options
= 0;
587 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
588 io
.ntcreatex
.in
.security_flags
= 0;
589 io
.ntcreatex
.in
.fname
= fname
;
591 torture_comment(tctx
, "EXCLUSIVE5: open with exclusive oplock\n");
592 ZERO_STRUCT(break_info
);
593 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
596 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
597 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
598 NTCREATEX_SHARE_ACCESS_WRITE
|
599 NTCREATEX_SHARE_ACCESS_DELETE
;
600 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
601 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
602 fnum
= io
.ntcreatex
.out
.file
.fnum
;
603 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
605 ZERO_STRUCT(break_info
);
607 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
609 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
610 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
611 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
612 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
613 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
614 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
615 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
616 torture_wait_for_oplock_break(tctx
);
617 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
618 CHECK_VAL(break_info
.failures
, 0);
620 smbcli_close(cli1
->tree
, fnum
);
621 smbcli_close(cli2
->tree
, fnum2
);
624 smb_raw_exit(cli1
->session
);
625 smb_raw_exit(cli2
->session
);
626 smbcli_deltree(cli1
->tree
, BASEDIR
);
630 static bool test_raw_oplock_exclusive6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
632 const char *fname1
= BASEDIR
"\\test_exclusive6_1.dat";
633 const char *fname2
= BASEDIR
"\\test_exclusive6_2.dat";
640 if (!torture_setup_dir(cli1
, BASEDIR
)) {
645 smbcli_unlink(cli1
->tree
, fname1
);
646 smbcli_unlink(cli1
->tree
, fname2
);
648 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
653 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
654 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
655 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
656 io
.ntcreatex
.in
.alloc_size
= 0;
657 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
658 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
659 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
660 io
.ntcreatex
.in
.create_options
= 0;
661 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
662 io
.ntcreatex
.in
.security_flags
= 0;
663 io
.ntcreatex
.in
.fname
= fname1
;
665 torture_comment(tctx
, "EXCLUSIVE6: open a file with an exclusive "
666 "oplock (share mode: none)\n");
667 ZERO_STRUCT(break_info
);
668 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
| NTCREATEX_FLAGS_REQUEST_OPLOCK
;
670 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
671 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
672 fnum
= io
.ntcreatex
.out
.file
.fnum
;
673 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
675 torture_comment(tctx
, "rename should not generate a break but get a "
676 "sharing violation\n");
678 rn
.generic
.level
= RAW_RENAME_RENAME
;
679 rn
.rename
.in
.pattern1
= fname1
;
680 rn
.rename
.in
.pattern2
= fname2
;
681 rn
.rename
.in
.attrib
= 0;
683 torture_comment(tctx
, "trying rename while first file open\n");
684 status
= smb_raw_rename(cli2
->tree
, &rn
);
686 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
687 torture_wait_for_oplock_break(tctx
);
688 CHECK_VAL(break_info
.count
, 0);
689 CHECK_VAL(break_info
.failures
, 0);
691 smbcli_close(cli1
->tree
, fnum
);
694 smb_raw_exit(cli1
->session
);
695 smb_raw_exit(cli2
->session
);
696 smbcli_deltree(cli1
->tree
, BASEDIR
);
701 * Exclusive version of batch19
703 static bool test_raw_oplock_exclusive7(struct torture_context
*tctx
,
704 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
706 const char *fname1
= BASEDIR
"\\test_exclusiv6_1.dat";
707 const char *fname2
= BASEDIR
"\\test_exclusiv6_2.dat";
708 const char *fname3
= BASEDIR
"\\test_exclusiv6_3.dat";
712 union smb_fileinfo qfi
;
713 union smb_setfileinfo sfi
;
717 if (!torture_setup_dir(cli1
, BASEDIR
)) {
722 smbcli_unlink(cli1
->tree
, fname1
);
723 smbcli_unlink(cli1
->tree
, fname2
);
724 smbcli_unlink(cli1
->tree
, fname3
);
726 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
732 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
733 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
734 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
735 io
.ntcreatex
.in
.alloc_size
= 0;
736 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
737 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
738 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
739 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
740 io
.ntcreatex
.in
.create_options
= 0;
741 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
742 io
.ntcreatex
.in
.security_flags
= 0;
743 io
.ntcreatex
.in
.fname
= fname1
;
745 torture_comment(tctx
, "open a file with an exclusive oplock (share "
747 ZERO_STRUCT(break_info
);
748 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
749 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
750 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
751 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
752 fnum
= io
.ntcreatex
.out
.file
.fnum
;
753 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
755 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
758 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
759 sfi
.generic
.in
.file
.path
= fname1
;
760 sfi
.rename_information
.in
.overwrite
= 0;
761 sfi
.rename_information
.in
.root_fid
= 0;
762 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
764 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
765 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
767 torture_wait_for_oplock_break(tctx
);
768 CHECK_VAL(break_info
.failures
, 0);
770 if (TARGET_IS_WINXP(tctx
)) {
771 /* XP incorrectly breaks to level2. */
772 CHECK_VAL(break_info
.count
, 1);
773 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
775 /* Exclusive oplocks should not be broken on rename. */
776 CHECK_VAL(break_info
.failures
, 0);
777 CHECK_VAL(break_info
.count
, 0);
781 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
782 qfi
.generic
.in
.file
.fnum
= fnum
;
784 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
785 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
786 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
788 /* Try breaking to level2 and then see if rename breaks the level2.*/
789 ZERO_STRUCT(break_info
);
790 io
.ntcreatex
.in
.fname
= fname2
;
791 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
792 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
793 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
794 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
796 torture_wait_for_oplock_break(tctx
);
797 CHECK_VAL(break_info
.failures
, 0);
799 if (TARGET_IS_WINXP(tctx
)) {
800 /* XP already broke to level2. */
801 CHECK_VAL(break_info
.failures
, 0);
802 CHECK_VAL(break_info
.count
, 0);
804 /* Break to level 2 expected. */
805 CHECK_VAL(break_info
.count
, 1);
806 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
809 ZERO_STRUCT(break_info
);
810 sfi
.generic
.in
.file
.path
= fname2
;
811 sfi
.rename_information
.in
.overwrite
= 0;
812 sfi
.rename_information
.in
.root_fid
= 0;
813 sfi
.rename_information
.in
.new_name
= fname1
+strlen(BASEDIR
)+1;
815 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
816 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
818 /* Level2 oplocks are not broken on rename. */
819 torture_wait_for_oplock_break(tctx
);
820 CHECK_VAL(break_info
.failures
, 0);
821 CHECK_VAL(break_info
.count
, 0);
823 /* Close and re-open file with oplock. */
824 smbcli_close(cli1
->tree
, fnum
);
825 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
826 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
827 fnum
= io
.ntcreatex
.out
.file
.fnum
;
828 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
830 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
831 "should not trigger a break nor a violation\n");
832 ZERO_STRUCT(break_info
);
834 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
835 sfi
.generic
.in
.file
.fnum
= fnum
;
836 sfi
.rename_information
.in
.overwrite
= 0;
837 sfi
.rename_information
.in
.root_fid
= 0;
838 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
840 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
841 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
843 torture_wait_for_oplock_break(tctx
);
844 if (TARGET_IS_WINXP(tctx
)) {
845 /* XP incorrectly breaks to level2. */
846 CHECK_VAL(break_info
.count
, 1);
847 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
849 CHECK_VAL(break_info
.count
, 0);
853 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
854 qfi
.generic
.in
.file
.fnum
= fnum
;
856 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
857 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
858 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
861 smbcli_close(cli1
->tree
, fnum
);
862 smbcli_close(cli2
->tree
, fnum2
);
864 smb_raw_exit(cli1
->session
);
865 smb_raw_exit(cli2
->session
);
866 smbcli_deltree(cli1
->tree
, BASEDIR
);
870 static bool test_raw_oplock_batch1(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
872 const char *fname
= BASEDIR
"\\test_batch1.dat";
876 union smb_unlink unl
;
880 if (!torture_setup_dir(cli1
, BASEDIR
)) {
885 smbcli_unlink(cli1
->tree
, fname
);
887 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
892 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
893 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
894 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
895 io
.ntcreatex
.in
.alloc_size
= 0;
896 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
897 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
898 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
899 io
.ntcreatex
.in
.create_options
= 0;
900 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
901 io
.ntcreatex
.in
.security_flags
= 0;
902 io
.ntcreatex
.in
.fname
= fname
;
905 with a batch oplock we get a break
907 torture_comment(tctx
, "BATCH1: open with batch oplock\n");
908 ZERO_STRUCT(break_info
);
909 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
910 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
911 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
912 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
913 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
914 fnum
= io
.ntcreatex
.out
.file
.fnum
;
915 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
917 torture_comment(tctx
, "unlink should generate a break\n");
918 unl
.unlink
.in
.pattern
= fname
;
919 unl
.unlink
.in
.attrib
= 0;
920 status
= smb_raw_unlink(cli2
->tree
, &unl
);
921 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
923 torture_wait_for_oplock_break(tctx
);
924 CHECK_VAL(break_info
.count
, 1);
925 CHECK_VAL(break_info
.fnum
, fnum
);
926 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
927 CHECK_VAL(break_info
.failures
, 0);
929 torture_comment(tctx
, "2nd unlink should not generate a break\n");
930 ZERO_STRUCT(break_info
);
931 status
= smb_raw_unlink(cli2
->tree
, &unl
);
932 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
934 torture_wait_for_oplock_break(tctx
);
935 CHECK_VAL(break_info
.count
, 0);
937 torture_comment(tctx
, "writing should generate a self break to none\n");
938 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
940 torture_wait_for_oplock_break(tctx
);
941 torture_wait_for_oplock_break(tctx
);
942 CHECK_VAL(break_info
.count
, 1);
943 CHECK_VAL(break_info
.fnum
, fnum
);
944 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
945 CHECK_VAL(break_info
.failures
, 0);
947 smbcli_close(cli1
->tree
, fnum
);
950 smb_raw_exit(cli1
->session
);
951 smb_raw_exit(cli2
->session
);
952 smbcli_deltree(cli1
->tree
, BASEDIR
);
956 static bool test_raw_oplock_batch2(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
958 const char *fname
= BASEDIR
"\\test_batch2.dat";
962 union smb_unlink unl
;
966 if (!torture_setup_dir(cli1
, BASEDIR
)) {
971 smbcli_unlink(cli1
->tree
, fname
);
973 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
978 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
979 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
980 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
981 io
.ntcreatex
.in
.alloc_size
= 0;
982 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
983 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
984 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
985 io
.ntcreatex
.in
.create_options
= 0;
986 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
987 io
.ntcreatex
.in
.security_flags
= 0;
988 io
.ntcreatex
.in
.fname
= fname
;
990 torture_comment(tctx
, "BATCH2: open with batch oplock\n");
991 ZERO_STRUCT(break_info
);
992 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
993 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
994 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
995 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
996 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
997 fnum
= io
.ntcreatex
.out
.file
.fnum
;
998 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1000 torture_comment(tctx
, "unlink should generate a break, which we ack as break to none\n");
1001 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_none
, cli1
->tree
);
1002 unl
.unlink
.in
.pattern
= fname
;
1003 unl
.unlink
.in
.attrib
= 0;
1004 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1005 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1007 torture_wait_for_oplock_break(tctx
);
1008 CHECK_VAL(break_info
.count
, 1);
1009 CHECK_VAL(break_info
.fnum
, fnum
);
1010 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1011 CHECK_VAL(break_info
.failures
, 0);
1013 torture_comment(tctx
, "2nd unlink should not generate a break\n");
1014 ZERO_STRUCT(break_info
);
1015 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1016 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1018 torture_wait_for_oplock_break(tctx
);
1019 CHECK_VAL(break_info
.count
, 0);
1021 torture_comment(tctx
, "writing should not generate a break\n");
1022 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1024 torture_wait_for_oplock_break(tctx
);
1025 CHECK_VAL(break_info
.count
, 0);
1027 smbcli_close(cli1
->tree
, fnum
);
1030 smb_raw_exit(cli1
->session
);
1031 smb_raw_exit(cli2
->session
);
1032 smbcli_deltree(cli1
->tree
, BASEDIR
);
1036 static bool test_raw_oplock_batch3(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1038 const char *fname
= BASEDIR
"\\test_batch3.dat";
1042 union smb_unlink unl
;
1045 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1050 smbcli_unlink(cli1
->tree
, fname
);
1052 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1055 base ntcreatex parms
1057 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1058 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1059 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1060 io
.ntcreatex
.in
.alloc_size
= 0;
1061 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1062 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1063 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1064 io
.ntcreatex
.in
.create_options
= 0;
1065 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1066 io
.ntcreatex
.in
.security_flags
= 0;
1067 io
.ntcreatex
.in
.fname
= fname
;
1069 torture_comment(tctx
, "BATCH3: if we close on break then the unlink can succeed\n");
1070 ZERO_STRUCT(break_info
);
1071 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1072 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1073 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1074 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1075 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1076 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1077 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1078 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1080 unl
.unlink
.in
.pattern
= fname
;
1081 unl
.unlink
.in
.attrib
= 0;
1082 ZERO_STRUCT(break_info
);
1083 status
= smb_raw_unlink(cli2
->tree
, &unl
);
1084 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1086 torture_wait_for_oplock_break(tctx
);
1087 CHECK_VAL(break_info
.count
, 1);
1088 CHECK_VAL(break_info
.fnum
, fnum
);
1089 CHECK_VAL(break_info
.level
, 1);
1090 CHECK_VAL(break_info
.failures
, 0);
1092 smbcli_close(cli1
->tree
, fnum
);
1095 smb_raw_exit(cli1
->session
);
1096 smb_raw_exit(cli2
->session
);
1097 smbcli_deltree(cli1
->tree
, BASEDIR
);
1101 static bool test_raw_oplock_batch4(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1103 const char *fname
= BASEDIR
"\\test_batch4.dat";
1110 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1115 smbcli_unlink(cli1
->tree
, fname
);
1117 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1120 base ntcreatex parms
1122 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1123 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1124 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1125 io
.ntcreatex
.in
.alloc_size
= 0;
1126 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1127 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1128 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1129 io
.ntcreatex
.in
.create_options
= 0;
1130 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1131 io
.ntcreatex
.in
.security_flags
= 0;
1132 io
.ntcreatex
.in
.fname
= fname
;
1134 torture_comment(tctx
, "BATCH4: a self read should not cause a break\n");
1135 ZERO_STRUCT(break_info
);
1136 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1138 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1139 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1140 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1141 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1142 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1143 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1144 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1146 rd
.readx
.level
= RAW_READ_READX
;
1147 rd
.readx
.in
.file
.fnum
= fnum
;
1148 rd
.readx
.in
.mincnt
= 1;
1149 rd
.readx
.in
.maxcnt
= 1;
1150 rd
.readx
.in
.offset
= 0;
1151 rd
.readx
.in
.remaining
= 0;
1152 rd
.readx
.in
.read_for_execute
= false;
1153 status
= smb_raw_read(cli1
->tree
, &rd
);
1154 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1155 torture_wait_for_oplock_break(tctx
);
1156 CHECK_VAL(break_info
.count
, 0);
1157 CHECK_VAL(break_info
.failures
, 0);
1159 smbcli_close(cli1
->tree
, fnum
);
1162 smb_raw_exit(cli1
->session
);
1163 smb_raw_exit(cli2
->session
);
1164 smbcli_deltree(cli1
->tree
, BASEDIR
);
1168 static bool test_raw_oplock_batch5(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1170 const char *fname
= BASEDIR
"\\test_batch5.dat";
1176 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1181 smbcli_unlink(cli1
->tree
, fname
);
1183 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1186 base ntcreatex parms
1188 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1189 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1190 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1191 io
.ntcreatex
.in
.alloc_size
= 0;
1192 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1193 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1194 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1195 io
.ntcreatex
.in
.create_options
= 0;
1196 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1197 io
.ntcreatex
.in
.security_flags
= 0;
1198 io
.ntcreatex
.in
.fname
= fname
;
1200 torture_comment(tctx
, "BATCH5: a 2nd open should give a break\n");
1201 ZERO_STRUCT(break_info
);
1202 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1204 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1205 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1206 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1207 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1208 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1209 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1210 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1212 ZERO_STRUCT(break_info
);
1214 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1215 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1216 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
1218 torture_wait_for_oplock_break(tctx
);
1219 CHECK_VAL(break_info
.count
, 1);
1220 CHECK_VAL(break_info
.fnum
, fnum
);
1221 CHECK_VAL(break_info
.level
, 1);
1222 CHECK_VAL(break_info
.failures
, 0);
1224 smbcli_close(cli1
->tree
, fnum
);
1227 smb_raw_exit(cli1
->session
);
1228 smb_raw_exit(cli2
->session
);
1229 smbcli_deltree(cli1
->tree
, BASEDIR
);
1233 static bool test_raw_oplock_batch6(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1235 const char *fname
= BASEDIR
"\\test_batch6.dat";
1239 uint16_t fnum
=0, fnum2
=0;
1242 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1247 smbcli_unlink(cli1
->tree
, fname
);
1249 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1250 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1253 base ntcreatex parms
1255 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1256 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1257 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1258 io
.ntcreatex
.in
.alloc_size
= 0;
1259 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1260 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1261 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1262 io
.ntcreatex
.in
.create_options
= 0;
1263 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1264 io
.ntcreatex
.in
.security_flags
= 0;
1265 io
.ntcreatex
.in
.fname
= fname
;
1267 torture_comment(tctx
, "BATCH6: a 2nd open should give a break to level II if the first open allowed shared read\n");
1268 ZERO_STRUCT(break_info
);
1270 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
1271 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
1272 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1273 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1274 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1275 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1276 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1277 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1278 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1280 ZERO_STRUCT(break_info
);
1282 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1283 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1284 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1285 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1287 //torture_wait_for_oplock_break(tctx);
1288 CHECK_VAL(break_info
.count
, 1);
1289 CHECK_VAL(break_info
.fnum
, fnum
);
1290 CHECK_VAL(break_info
.level
, 1);
1291 CHECK_VAL(break_info
.failures
, 0);
1292 ZERO_STRUCT(break_info
);
1294 torture_comment(tctx
, "write should trigger a break to none on both\n");
1295 smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
1297 /* We expect two breaks */
1298 torture_wait_for_oplock_break(tctx
);
1299 torture_wait_for_oplock_break(tctx
);
1301 CHECK_VAL(break_info
.count
, 2);
1302 CHECK_VAL(break_info
.level
, 0);
1303 CHECK_VAL(break_info
.failures
, 0);
1305 smbcli_close(cli1
->tree
, fnum
);
1306 smbcli_close(cli2
->tree
, fnum2
);
1309 smb_raw_exit(cli1
->session
);
1310 smb_raw_exit(cli2
->session
);
1311 smbcli_deltree(cli1
->tree
, BASEDIR
);
1315 static bool test_raw_oplock_batch7(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1317 const char *fname
= BASEDIR
"\\test_batch7.dat";
1321 uint16_t fnum
=0, fnum2
=0;
1323 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1328 smbcli_unlink(cli1
->tree
, fname
);
1330 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1333 base ntcreatex parms
1335 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1336 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1337 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1338 io
.ntcreatex
.in
.alloc_size
= 0;
1339 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1340 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1341 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1342 io
.ntcreatex
.in
.create_options
= 0;
1343 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1344 io
.ntcreatex
.in
.security_flags
= 0;
1345 io
.ntcreatex
.in
.fname
= fname
;
1347 torture_comment(tctx
, "BATCH7: a 2nd open should get an oplock when we close instead of ack\n");
1348 ZERO_STRUCT(break_info
);
1349 smbcli_oplock_handler(cli1
->transport
, oplock_handler_close
, cli1
->tree
);
1351 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1352 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1353 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1354 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1355 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1356 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1357 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1358 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1359 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1361 ZERO_STRUCT(break_info
);
1363 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1364 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1365 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1366 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1367 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1368 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1369 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1371 torture_wait_for_oplock_break(tctx
);
1372 CHECK_VAL(break_info
.count
, 1);
1373 CHECK_VAL(break_info
.fnum
, fnum2
);
1374 CHECK_VAL(break_info
.level
, 1);
1375 CHECK_VAL(break_info
.failures
, 0);
1377 smbcli_close(cli2
->tree
, fnum
);
1380 smb_raw_exit(cli1
->session
);
1381 smb_raw_exit(cli2
->session
);
1382 smbcli_deltree(cli1
->tree
, BASEDIR
);
1386 static bool test_raw_oplock_batch8(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1388 const char *fname
= BASEDIR
"\\test_batch8.dat";
1392 uint16_t fnum
=0, fnum2
=0;
1394 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1399 smbcli_unlink(cli1
->tree
, fname
);
1401 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1404 base ntcreatex parms
1406 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1407 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1408 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1409 io
.ntcreatex
.in
.alloc_size
= 0;
1410 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1411 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1412 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1413 io
.ntcreatex
.in
.create_options
= 0;
1414 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1415 io
.ntcreatex
.in
.security_flags
= 0;
1416 io
.ntcreatex
.in
.fname
= fname
;
1418 torture_comment(tctx
, "BATCH8: open with batch oplock\n");
1419 ZERO_STRUCT(break_info
);
1420 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1422 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1423 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1424 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1425 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1426 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1427 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1428 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1430 ZERO_STRUCT(break_info
);
1431 torture_comment(tctx
, "second open with attributes only shouldn't cause oplock break\n");
1433 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1434 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1435 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1436 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1437 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1438 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1439 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1440 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
1441 torture_wait_for_oplock_break(tctx
);
1442 CHECK_VAL(break_info
.count
, 0);
1443 CHECK_VAL(break_info
.failures
, 0);
1445 smbcli_close(cli1
->tree
, fnum
);
1446 smbcli_close(cli2
->tree
, fnum2
);
1449 smb_raw_exit(cli1
->session
);
1450 smb_raw_exit(cli2
->session
);
1451 smbcli_deltree(cli1
->tree
, BASEDIR
);
1455 static bool test_raw_oplock_batch9(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1457 const char *fname
= BASEDIR
"\\test_batch9.dat";
1461 uint16_t fnum
=0, fnum2
=0;
1464 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1469 smbcli_unlink(cli1
->tree
, fname
);
1471 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1474 base ntcreatex parms
1476 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1477 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1478 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1479 io
.ntcreatex
.in
.alloc_size
= 0;
1480 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1481 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1482 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1483 io
.ntcreatex
.in
.create_options
= 0;
1484 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1485 io
.ntcreatex
.in
.security_flags
= 0;
1486 io
.ntcreatex
.in
.fname
= fname
;
1488 torture_comment(tctx
, "BATCH9: open with attributes only can create file\n");
1490 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1491 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1492 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1493 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1494 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1495 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1496 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1497 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1498 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1500 torture_comment(tctx
, "Subsequent normal open should break oplock on attribute only open to level II\n");
1502 ZERO_STRUCT(break_info
);
1503 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1505 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1506 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1507 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1508 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1509 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1510 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1511 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1512 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1513 torture_wait_for_oplock_break(tctx
);
1514 CHECK_VAL(break_info
.count
, 1);
1515 CHECK_VAL(break_info
.fnum
, fnum
);
1516 CHECK_VAL(break_info
.failures
, 0);
1517 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
1518 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1519 smbcli_close(cli2
->tree
, fnum2
);
1521 torture_comment(tctx
, "third oplocked open should grant level2 without break\n");
1522 ZERO_STRUCT(break_info
);
1523 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1524 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1525 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1526 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1527 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1528 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1529 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1530 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1531 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1532 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1533 torture_wait_for_oplock_break(tctx
);
1534 CHECK_VAL(break_info
.count
, 0);
1535 CHECK_VAL(break_info
.failures
, 0);
1536 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1538 ZERO_STRUCT(break_info
);
1540 torture_comment(tctx
, "write should trigger a break to none on both\n");
1541 smbcli_write(cli2
->tree
, fnum2
, 0, &c
, 0, 1);
1543 /* We expect two breaks */
1544 torture_wait_for_oplock_break(tctx
);
1545 torture_wait_for_oplock_break(tctx
);
1547 CHECK_VAL(break_info
.count
, 2);
1548 CHECK_VAL(break_info
.level
, 0);
1549 CHECK_VAL(break_info
.failures
, 0);
1551 smbcli_close(cli1
->tree
, fnum
);
1552 smbcli_close(cli2
->tree
, fnum2
);
1555 smb_raw_exit(cli1
->session
);
1556 smb_raw_exit(cli2
->session
);
1557 smbcli_deltree(cli1
->tree
, BASEDIR
);
1561 static bool test_raw_oplock_batch10(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1563 const char *fname
= BASEDIR
"\\test_batch10.dat";
1567 uint16_t fnum
=0, fnum2
=0;
1569 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1574 smbcli_unlink(cli1
->tree
, fname
);
1576 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1579 base ntcreatex parms
1581 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1582 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1583 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1584 io
.ntcreatex
.in
.alloc_size
= 0;
1585 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1586 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1587 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1588 io
.ntcreatex
.in
.create_options
= 0;
1589 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1590 io
.ntcreatex
.in
.security_flags
= 0;
1591 io
.ntcreatex
.in
.fname
= fname
;
1593 torture_comment(tctx
, "BATCH10: Open with oplock after a non-oplock open should grant level2\n");
1594 ZERO_STRUCT(break_info
);
1595 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
1596 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1597 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1598 NTCREATEX_SHARE_ACCESS_WRITE
|
1599 NTCREATEX_SHARE_ACCESS_DELETE
;
1600 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1601 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1602 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1603 torture_wait_for_oplock_break(tctx
);
1604 CHECK_VAL(break_info
.count
, 0);
1605 CHECK_VAL(break_info
.failures
, 0);
1606 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, 0);
1608 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
1610 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1611 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1612 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1613 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1614 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1615 NTCREATEX_SHARE_ACCESS_WRITE
|
1616 NTCREATEX_SHARE_ACCESS_DELETE
;
1617 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
1618 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1619 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1620 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1621 torture_wait_for_oplock_break(tctx
);
1622 CHECK_VAL(break_info
.count
, 0);
1623 CHECK_VAL(break_info
.failures
, 0);
1624 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1626 torture_comment(tctx
, "write should trigger a break to none\n");
1629 wr
.write
.level
= RAW_WRITE_WRITE
;
1630 wr
.write
.in
.file
.fnum
= fnum
;
1631 wr
.write
.in
.count
= 1;
1632 wr
.write
.in
.offset
= 0;
1633 wr
.write
.in
.remaining
= 0;
1634 wr
.write
.in
.data
= (const uint8_t *)"x";
1635 status
= smb_raw_write(cli1
->tree
, &wr
);
1636 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1639 torture_wait_for_oplock_break(tctx
);
1641 CHECK_VAL(break_info
.count
, 1);
1642 CHECK_VAL(break_info
.fnum
, fnum2
);
1643 CHECK_VAL(break_info
.level
, 0);
1644 CHECK_VAL(break_info
.failures
, 0);
1646 smbcli_close(cli1
->tree
, fnum
);
1647 smbcli_close(cli2
->tree
, fnum2
);
1650 smb_raw_exit(cli1
->session
);
1651 smb_raw_exit(cli2
->session
);
1652 smbcli_deltree(cli1
->tree
, BASEDIR
);
1656 static bool test_raw_oplock_batch11(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1658 const char *fname
= BASEDIR
"\\test_batch11.dat";
1662 union smb_setfileinfo sfi
;
1665 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1670 smbcli_unlink(cli1
->tree
, fname
);
1672 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1675 base ntcreatex parms
1677 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1678 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1679 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1680 io
.ntcreatex
.in
.alloc_size
= 0;
1681 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1682 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_WRITE
;
1683 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1684 io
.ntcreatex
.in
.create_options
= 0;
1685 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1686 io
.ntcreatex
.in
.security_flags
= 0;
1687 io
.ntcreatex
.in
.fname
= fname
;
1689 /* Test if a set-eof on pathname breaks an exclusive oplock. */
1690 torture_comment(tctx
, "BATCH11: Test if setpathinfo set EOF breaks oplocks.\n");
1692 ZERO_STRUCT(break_info
);
1694 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1695 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1696 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1697 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1698 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1699 NTCREATEX_SHARE_ACCESS_WRITE
|
1700 NTCREATEX_SHARE_ACCESS_DELETE
;
1701 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1702 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1703 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1704 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1705 torture_wait_for_oplock_break(tctx
);
1706 CHECK_VAL(break_info
.count
, 0);
1707 CHECK_VAL(break_info
.failures
, 0);
1708 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1711 sfi
.generic
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
1712 sfi
.generic
.in
.file
.path
= fname
;
1713 sfi
.end_of_file_info
.in
.size
= 100;
1715 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1716 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1718 torture_wait_for_oplock_break(tctx
);
1719 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1720 CHECK_VAL(break_info
.failures
, 0);
1721 CHECK_VAL(break_info
.level
, 0);
1723 smbcli_close(cli1
->tree
, fnum
);
1726 smb_raw_exit(cli1
->session
);
1727 smb_raw_exit(cli2
->session
);
1728 smbcli_deltree(cli1
->tree
, BASEDIR
);
1732 static bool test_raw_oplock_batch12(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1734 const char *fname
= BASEDIR
"\\test_batch12.dat";
1738 union smb_setfileinfo sfi
;
1741 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1746 smbcli_unlink(cli1
->tree
, fname
);
1748 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1751 base ntcreatex parms
1753 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1754 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1755 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1756 io
.ntcreatex
.in
.alloc_size
= 0;
1757 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1758 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1759 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1760 io
.ntcreatex
.in
.create_options
= 0;
1761 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1762 io
.ntcreatex
.in
.security_flags
= 0;
1763 io
.ntcreatex
.in
.fname
= fname
;
1765 /* Test if a set-allocation size on pathname breaks an exclusive oplock. */
1766 torture_comment(tctx
, "BATCH12: Test if setpathinfo allocation size breaks oplocks.\n");
1768 ZERO_STRUCT(break_info
);
1769 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1771 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1772 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1773 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1774 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1775 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1776 NTCREATEX_SHARE_ACCESS_WRITE
|
1777 NTCREATEX_SHARE_ACCESS_DELETE
;
1778 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
1779 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1780 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1781 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1782 torture_wait_for_oplock_break(tctx
);
1783 CHECK_VAL(break_info
.count
, 0);
1784 CHECK_VAL(break_info
.failures
, 0);
1785 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1788 sfi
.generic
.level
= SMB_SFILEINFO_ALLOCATION_INFORMATION
;
1789 sfi
.generic
.in
.file
.path
= fname
;
1790 sfi
.allocation_info
.in
.alloc_size
= 65536 * 8;
1792 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
1793 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1795 torture_wait_for_oplock_break(tctx
);
1796 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1797 CHECK_VAL(break_info
.failures
, 0);
1798 CHECK_VAL(break_info
.level
, 0);
1800 smbcli_close(cli1
->tree
, fnum
);
1803 smb_raw_exit(cli1
->session
);
1804 smb_raw_exit(cli2
->session
);
1805 smbcli_deltree(cli1
->tree
, BASEDIR
);
1809 static bool test_raw_oplock_batch13(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1811 const char *fname
= BASEDIR
"\\test_batch13.dat";
1815 uint16_t fnum
=0, fnum2
=0;
1817 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1822 smbcli_unlink(cli1
->tree
, fname
);
1824 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1825 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1828 base ntcreatex parms
1830 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1831 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1832 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1833 io
.ntcreatex
.in
.alloc_size
= 0;
1834 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1835 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1836 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1837 io
.ntcreatex
.in
.create_options
= 0;
1838 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1839 io
.ntcreatex
.in
.security_flags
= 0;
1840 io
.ntcreatex
.in
.fname
= fname
;
1842 torture_comment(tctx
, "BATCH13: open with batch oplock\n");
1843 ZERO_STRUCT(break_info
);
1845 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1846 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1847 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1848 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1849 NTCREATEX_SHARE_ACCESS_WRITE
|
1850 NTCREATEX_SHARE_ACCESS_DELETE
;
1851 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1852 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1853 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1854 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1856 ZERO_STRUCT(break_info
);
1858 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE dispostion causes oplock break\n");
1860 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1861 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1862 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1863 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1864 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1865 NTCREATEX_SHARE_ACCESS_WRITE
|
1866 NTCREATEX_SHARE_ACCESS_DELETE
;
1867 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1868 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1869 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1870 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1871 torture_wait_for_oplock_break(tctx
);
1872 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1873 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1874 CHECK_VAL(break_info
.failures
, 0);
1876 smbcli_close(cli1
->tree
, fnum
);
1877 smbcli_close(cli2
->tree
, fnum2
);
1880 smb_raw_exit(cli1
->session
);
1881 smb_raw_exit(cli2
->session
);
1882 smbcli_deltree(cli1
->tree
, BASEDIR
);
1886 static bool test_raw_oplock_batch14(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1888 const char *fname
= BASEDIR
"\\test_batch14.dat";
1892 uint16_t fnum
=0, fnum2
=0;
1894 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1899 smbcli_unlink(cli1
->tree
, fname
);
1901 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1904 base ntcreatex parms
1906 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1907 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1908 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1909 io
.ntcreatex
.in
.alloc_size
= 0;
1910 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1911 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1912 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1913 io
.ntcreatex
.in
.create_options
= 0;
1914 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1915 io
.ntcreatex
.in
.security_flags
= 0;
1916 io
.ntcreatex
.in
.fname
= fname
;
1918 torture_comment(tctx
, "BATCH14: open with batch oplock\n");
1919 ZERO_STRUCT(break_info
);
1921 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1922 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1923 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1924 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1925 NTCREATEX_SHARE_ACCESS_WRITE
|
1926 NTCREATEX_SHARE_ACCESS_DELETE
;
1927 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
1928 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1929 fnum
= io
.ntcreatex
.out
.file
.fnum
;
1930 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
1932 ZERO_STRUCT(break_info
);
1934 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_SUPERSEDE dispostion causes oplock break\n");
1936 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
1937 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
1938 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
1939 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
1940 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
1941 NTCREATEX_SHARE_ACCESS_WRITE
|
1942 NTCREATEX_SHARE_ACCESS_DELETE
;
1943 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE
;
1944 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
1945 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
1946 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
1947 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
1949 torture_wait_for_oplock_break(tctx
);
1950 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
1951 CHECK_VAL(break_info
.failures
, 0);
1953 smbcli_close(cli1
->tree
, fnum
);
1954 smbcli_close(cli2
->tree
, fnum2
);
1956 smb_raw_exit(cli1
->session
);
1957 smb_raw_exit(cli2
->session
);
1958 smbcli_deltree(cli1
->tree
, BASEDIR
);
1962 static bool test_raw_oplock_batch15(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
1964 const char *fname
= BASEDIR
"\\test_batch15.dat";
1968 union smb_fileinfo qfi
;
1971 if (!torture_setup_dir(cli1
, BASEDIR
)) {
1976 smbcli_unlink(cli1
->tree
, fname
);
1978 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
1981 base ntcreatex parms
1983 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
1984 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
1985 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
1986 io
.ntcreatex
.in
.alloc_size
= 0;
1987 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
1988 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1989 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
1990 io
.ntcreatex
.in
.create_options
= 0;
1991 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
1992 io
.ntcreatex
.in
.security_flags
= 0;
1993 io
.ntcreatex
.in
.fname
= fname
;
1995 /* Test if a qpathinfo all info on pathname breaks a batch oplock. */
1996 torture_comment(tctx
, "BATCH15: Test if qpathinfo all info breaks a batch oplock (should not).\n");
1998 ZERO_STRUCT(break_info
);
2000 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2001 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2002 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2003 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2004 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2005 NTCREATEX_SHARE_ACCESS_WRITE
|
2006 NTCREATEX_SHARE_ACCESS_DELETE
;
2007 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2008 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
2009 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2010 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2011 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2013 torture_wait_for_oplock_break(tctx
);
2014 CHECK_VAL(break_info
.count
, 0);
2015 CHECK_VAL(break_info
.failures
, 0);
2016 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2019 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2020 qfi
.generic
.in
.file
.path
= fname
;
2022 status
= smb_raw_pathinfo(cli2
->tree
, tctx
, &qfi
);
2023 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2025 torture_wait_for_oplock_break(tctx
);
2026 CHECK_VAL(break_info
.count
, 0);
2028 smbcli_close(cli1
->tree
, fnum
);
2031 smb_raw_exit(cli1
->session
);
2032 smb_raw_exit(cli2
->session
);
2033 smbcli_deltree(cli1
->tree
, BASEDIR
);
2037 static bool test_raw_oplock_batch16(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2039 const char *fname
= BASEDIR
"\\test_batch16.dat";
2043 uint16_t fnum
=0, fnum2
=0;
2045 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2050 smbcli_unlink(cli1
->tree
, fname
);
2052 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2053 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2056 base ntcreatex parms
2058 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2059 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2060 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2061 io
.ntcreatex
.in
.alloc_size
= 0;
2062 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2063 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2064 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2065 io
.ntcreatex
.in
.create_options
= 0;
2066 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2067 io
.ntcreatex
.in
.security_flags
= 0;
2068 io
.ntcreatex
.in
.fname
= fname
;
2070 torture_comment(tctx
, "BATCH16: open with batch oplock\n");
2071 ZERO_STRUCT(break_info
);
2073 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2074 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2075 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2076 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2077 NTCREATEX_SHARE_ACCESS_WRITE
|
2078 NTCREATEX_SHARE_ACCESS_DELETE
;
2079 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2080 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2081 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2082 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2084 ZERO_STRUCT(break_info
);
2086 torture_comment(tctx
, "second open with attributes only and NTCREATEX_DISP_OVERWRITE_IF dispostion causes oplock break\n");
2088 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2089 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2090 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2091 io
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_ATTRIBUTE
|SEC_FILE_WRITE_ATTRIBUTE
|SEC_STD_SYNCHRONIZE
;
2092 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2093 NTCREATEX_SHARE_ACCESS_WRITE
|
2094 NTCREATEX_SHARE_ACCESS_DELETE
;
2095 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
2096 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2097 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2098 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2099 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2101 torture_wait_for_oplock_break(tctx
);
2102 CHECK_VAL(break_info
.count
, get_break_level1_to_none_count(tctx
));
2103 CHECK_VAL(break_info
.failures
, 0);
2105 smbcli_close(cli1
->tree
, fnum
);
2106 smbcli_close(cli2
->tree
, fnum2
);
2109 smb_raw_exit(cli1
->session
);
2110 smb_raw_exit(cli2
->session
);
2111 smbcli_deltree(cli1
->tree
, BASEDIR
);
2115 static bool test_raw_oplock_batch17(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2117 const char *fname1
= BASEDIR
"\\test_batch17_1.dat";
2118 const char *fname2
= BASEDIR
"\\test_batch17_2.dat";
2122 union smb_rename rn
;
2125 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2130 smbcli_unlink(cli1
->tree
, fname1
);
2131 smbcli_unlink(cli1
->tree
, fname2
);
2133 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2136 base ntcreatex parms
2138 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2139 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2140 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2141 io
.ntcreatex
.in
.alloc_size
= 0;
2142 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2143 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2144 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2145 io
.ntcreatex
.in
.create_options
= 0;
2146 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2147 io
.ntcreatex
.in
.security_flags
= 0;
2148 io
.ntcreatex
.in
.fname
= fname1
;
2150 torture_comment(tctx
, "BATCH17: open a file with an batch oplock (share mode: none)\n");
2152 ZERO_STRUCT(break_info
);
2153 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2154 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2155 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2157 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2158 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2159 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2160 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2162 torture_comment(tctx
, "rename should trigger a break\n");
2164 rn
.generic
.level
= RAW_RENAME_RENAME
;
2165 rn
.rename
.in
.pattern1
= fname1
;
2166 rn
.rename
.in
.pattern2
= fname2
;
2167 rn
.rename
.in
.attrib
= 0;
2169 torture_comment(tctx
, "trying rename while first file open\n");
2170 status
= smb_raw_rename(cli2
->tree
, &rn
);
2171 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2173 torture_wait_for_oplock_break(tctx
);
2174 CHECK_VAL(break_info
.count
, 1);
2175 CHECK_VAL(break_info
.failures
, 0);
2176 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2178 smbcli_close(cli1
->tree
, fnum
);
2181 smb_raw_exit(cli1
->session
);
2182 smb_raw_exit(cli2
->session
);
2183 smbcli_deltree(cli1
->tree
, BASEDIR
);
2187 static bool test_raw_oplock_batch18(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2189 const char *fname1
= BASEDIR
"\\test_batch18_1.dat";
2190 const char *fname2
= BASEDIR
"\\test_batch18_2.dat";
2194 union smb_rename rn
;
2197 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2202 smbcli_unlink(cli1
->tree
, fname1
);
2203 smbcli_unlink(cli1
->tree
, fname2
);
2205 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2208 base ntcreatex parms
2210 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2211 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2212 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2213 io
.ntcreatex
.in
.alloc_size
= 0;
2214 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2215 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2216 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2217 io
.ntcreatex
.in
.create_options
= 0;
2218 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2219 io
.ntcreatex
.in
.security_flags
= 0;
2220 io
.ntcreatex
.in
.fname
= fname1
;
2222 torture_comment(tctx
, "BATCH18: open a file with an batch oplock (share mode: none)\n");
2224 ZERO_STRUCT(break_info
);
2225 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2226 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2227 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2229 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2230 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2231 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2232 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2234 torture_comment(tctx
, "ntrename should trigger a break\n");
2236 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
2237 rn
.ntrename
.in
.attrib
= 0;
2238 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
2239 rn
.ntrename
.in
.old_name
= fname1
;
2240 rn
.ntrename
.in
.new_name
= fname2
;
2241 torture_comment(tctx
, "trying rename while first file open\n");
2242 status
= smb_raw_rename(cli2
->tree
, &rn
);
2243 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2245 torture_wait_for_oplock_break(tctx
);
2246 CHECK_VAL(break_info
.count
, 1);
2247 CHECK_VAL(break_info
.failures
, 0);
2248 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2250 smbcli_close(cli1
->tree
, fnum
);
2253 smb_raw_exit(cli1
->session
);
2254 smb_raw_exit(cli2
->session
);
2255 smbcli_deltree(cli1
->tree
, BASEDIR
);
2259 static bool test_raw_oplock_batch19(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2261 const char *fname1
= BASEDIR
"\\test_batch19_1.dat";
2262 const char *fname2
= BASEDIR
"\\test_batch19_2.dat";
2263 const char *fname3
= BASEDIR
"\\test_batch19_3.dat";
2267 union smb_fileinfo qfi
;
2268 union smb_setfileinfo sfi
;
2271 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2276 smbcli_unlink(cli1
->tree
, fname1
);
2277 smbcli_unlink(cli1
->tree
, fname2
);
2278 smbcli_unlink(cli1
->tree
, fname3
);
2280 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2283 base ntcreatex parms
2285 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2286 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2287 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2288 io
.ntcreatex
.in
.alloc_size
= 0;
2289 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2290 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2291 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2292 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2293 io
.ntcreatex
.in
.create_options
= 0;
2294 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2295 io
.ntcreatex
.in
.security_flags
= 0;
2296 io
.ntcreatex
.in
.fname
= fname1
;
2298 torture_comment(tctx
, "BATCH19: open a file with an batch oplock (share mode: none)\n");
2299 ZERO_STRUCT(break_info
);
2300 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2301 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2302 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2303 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2304 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2305 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2306 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2308 torture_comment(tctx
, "setpathinfo rename info should trigger a break "
2311 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2312 sfi
.generic
.in
.file
.path
= fname1
;
2313 sfi
.rename_information
.in
.overwrite
= 0;
2314 sfi
.rename_information
.in
.root_fid
= 0;
2315 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2317 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2318 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2320 torture_wait_for_oplock_break(tctx
);
2322 CHECK_VAL(break_info
.failures
, 0);
2324 if (TARGET_IS_WINXP(tctx
)) {
2325 /* Win XP breaks to level2. */
2326 CHECK_VAL(break_info
.count
, 1);
2327 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2328 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2329 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2330 /* Win2K3/2k8 incorrectly doesn't break at all. */
2331 CHECK_VAL(break_info
.count
, 0);
2333 /* win7/2k8r2 break to none. */
2334 CHECK_VAL(break_info
.count
, 1);
2335 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2339 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2340 qfi
.generic
.in
.file
.fnum
= fnum
;
2342 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2343 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2344 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2346 /* Close and re-open file with oplock. */
2347 smbcli_close(cli1
->tree
, fnum
);
2348 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2349 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2350 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2351 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2353 torture_comment(tctx
, "setfileinfo rename info on a client's own fid "
2354 "should not trigger a break nor a violation\n");
2355 ZERO_STRUCT(break_info
);
2357 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2358 sfi
.generic
.in
.file
.fnum
= fnum
;
2359 sfi
.rename_information
.in
.overwrite
= 0;
2360 sfi
.rename_information
.in
.root_fid
= 0;
2361 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2363 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2364 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2366 torture_wait_for_oplock_break(tctx
);
2367 if (TARGET_IS_WINXP(tctx
)) {
2368 /* XP incorrectly breaks to level2. */
2369 CHECK_VAL(break_info
.count
, 1);
2370 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2372 CHECK_VAL(break_info
.count
, 0);
2376 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2377 qfi
.generic
.in
.file
.fnum
= fnum
;
2379 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2380 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2381 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2384 smbcli_close(cli1
->tree
, fnum
);
2385 smb_raw_exit(cli1
->session
);
2386 smb_raw_exit(cli2
->session
);
2387 smbcli_deltree(cli1
->tree
, BASEDIR
);
2391 /****************************************************
2392 Called from raw-rename - we need oplock handling for
2393 this test so this is why it's in oplock.c, not rename.c
2394 ****************************************************/
2396 bool test_trans2rename(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2398 const char *fname1
= BASEDIR
"\\test_trans2rename_1.dat";
2399 const char *fname2
= BASEDIR
"\\test_trans2rename_2.dat";
2400 const char *fname3
= BASEDIR
"\\test_trans2rename_3.dat";
2404 union smb_fileinfo qfi
;
2405 union smb_setfileinfo sfi
;
2408 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2413 smbcli_unlink(cli1
->tree
, fname1
);
2414 smbcli_unlink(cli1
->tree
, fname2
);
2415 smbcli_unlink(cli1
->tree
, fname3
);
2417 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2420 base ntcreatex parms
2422 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2423 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2424 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2425 io
.ntcreatex
.in
.alloc_size
= 0;
2426 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2427 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2428 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
2429 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2430 io
.ntcreatex
.in
.create_options
= 0;
2431 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2432 io
.ntcreatex
.in
.security_flags
= 0;
2433 io
.ntcreatex
.in
.fname
= fname1
;
2435 torture_comment(tctx
, "open a file with an exclusive oplock (share mode: none)\n");
2436 ZERO_STRUCT(break_info
);
2437 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2438 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2439 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2440 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2441 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2442 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2444 torture_comment(tctx
, "setpathinfo rename info should not trigger a break nor a violation\n");
2446 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2447 sfi
.generic
.in
.file
.path
= fname1
;
2448 sfi
.rename_information
.in
.overwrite
= 0;
2449 sfi
.rename_information
.in
.root_fid
= 0;
2450 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2452 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2454 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2456 torture_wait_for_oplock_break(tctx
);
2457 CHECK_VAL(break_info
.count
, 0);
2460 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2461 qfi
.generic
.in
.file
.fnum
= fnum
;
2463 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2464 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2465 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2467 torture_comment(tctx
, "setfileinfo rename info should not trigger a break nor a violation\n");
2469 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2470 sfi
.generic
.in
.file
.fnum
= fnum
;
2471 sfi
.rename_information
.in
.overwrite
= 0;
2472 sfi
.rename_information
.in
.root_fid
= 0;
2473 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2475 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2476 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2478 torture_wait_for_oplock_break(tctx
);
2479 CHECK_VAL(break_info
.count
, 0);
2482 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2483 qfi
.generic
.in
.file
.fnum
= fnum
;
2485 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2486 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2487 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2490 smbcli_close(cli1
->tree
, fnum
);
2491 smb_raw_exit(cli1
->session
);
2492 smb_raw_exit(cli2
->session
);
2493 smbcli_deltree(cli1
->tree
, BASEDIR
);
2497 /****************************************************
2498 Called from raw-rename - we need oplock handling for
2499 this test so this is why it's in oplock.c, not rename.c
2500 ****************************************************/
2502 bool test_nttransrename(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
2504 const char *fname1
= BASEDIR
"\\test_nttransrename_1.dat";
2505 const char *fname2
= BASEDIR
"\\test_nttransrename_2.dat";
2509 union smb_fileinfo qfi
, qpi
;
2510 union smb_rename rn
;
2513 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2518 smbcli_unlink(cli1
->tree
, fname1
);
2519 smbcli_unlink(cli1
->tree
, fname2
);
2521 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2524 base ntcreatex parms
2526 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2527 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2528 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2529 io
.ntcreatex
.in
.alloc_size
= 0;
2530 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2531 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2532 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2533 io
.ntcreatex
.in
.create_options
= 0;
2534 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2535 io
.ntcreatex
.in
.security_flags
= 0;
2536 io
.ntcreatex
.in
.fname
= fname1
;
2538 torture_comment(tctx
, "nttrans_rename: open a file with an exclusive oplock (share mode: none)\n");
2539 ZERO_STRUCT(break_info
);
2540 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2541 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
2542 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2543 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2544 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2545 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
2547 torture_comment(tctx
, "nttrans_rename: should not trigger a break nor a share mode violation\n");
2549 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2550 rn
.nttrans
.in
.file
.fnum
= fnum
;
2551 rn
.nttrans
.in
.flags
= 0;
2552 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2554 status
= smb_raw_rename(cli1
->tree
, &rn
);
2555 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2557 torture_wait_for_oplock_break(tctx
);
2558 CHECK_VAL(break_info
.count
, 0);
2560 /* w2k3 does nothing, it doesn't rename the file */
2561 torture_comment(tctx
, "nttrans_rename: the server should have done nothing\n");
2563 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2564 qfi
.generic
.in
.file
.fnum
= fnum
;
2566 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2567 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2568 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname1
);
2571 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2572 qpi
.generic
.in
.file
.path
= fname1
;
2574 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2575 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2576 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2579 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2580 qpi
.generic
.in
.file
.path
= fname2
;
2582 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2583 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2585 torture_comment(tctx
, "nttrans_rename: after closing the file the file is still not renamed\n");
2586 status
= smbcli_close(cli1
->tree
, fnum
);
2587 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2590 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2591 qpi
.generic
.in
.file
.path
= fname1
;
2593 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2594 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2595 CHECK_STRMATCH(qpi
.all_info
.out
.fname
.s
, fname1
);
2598 qpi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2599 qpi
.generic
.in
.file
.path
= fname2
;
2601 status
= smb_raw_pathinfo(cli1
->tree
, tctx
, &qpi
);
2602 CHECK_STATUS(tctx
, status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
2604 torture_comment(tctx
, "nttrans_rename: rename with an invalid handle gives NT_STATUS_INVALID_HANDLE\n");
2606 rn
.generic
.level
= RAW_RENAME_NTTRANS
;
2607 rn
.nttrans
.in
.file
.fnum
= fnum
+1;
2608 rn
.nttrans
.in
.flags
= 0;
2609 rn
.nttrans
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2611 status
= smb_raw_rename(cli1
->tree
, &rn
);
2613 CHECK_STATUS(tctx
, status
, NT_STATUS_INVALID_HANDLE
);
2616 smb_raw_exit(cli1
->session
);
2617 smbcli_deltree(cli1
->tree
, BASEDIR
);
2622 static bool test_raw_oplock_batch20(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2624 const char *fname1
= BASEDIR
"\\test_batch20_1.dat";
2625 const char *fname2
= BASEDIR
"\\test_batch20_2.dat";
2626 const char *fname3
= BASEDIR
"\\test_batch20_3.dat";
2630 union smb_fileinfo qfi
;
2631 union smb_setfileinfo sfi
;
2632 uint16_t fnum
=0,fnum2
=0;
2634 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2639 smbcli_unlink(cli1
->tree
, fname1
);
2640 smbcli_unlink(cli1
->tree
, fname2
);
2641 smbcli_unlink(cli1
->tree
, fname3
);
2643 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2646 base ntcreatex parms
2648 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2649 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2650 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2651 io
.ntcreatex
.in
.alloc_size
= 0;
2652 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2653 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2654 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2655 io
.ntcreatex
.in
.create_options
= 0;
2656 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2657 io
.ntcreatex
.in
.security_flags
= 0;
2658 io
.ntcreatex
.in
.fname
= fname1
;
2660 torture_comment(tctx
, "BATCH20: open a file with an batch oplock (share mode: all)\n");
2661 ZERO_STRUCT(break_info
);
2662 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2663 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2664 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2665 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2666 NTCREATEX_SHARE_ACCESS_WRITE
|
2667 NTCREATEX_SHARE_ACCESS_DELETE
;
2668 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2669 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2670 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2671 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2674 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2675 sfi
.generic
.in
.file
.path
= fname1
;
2676 sfi
.rename_information
.in
.overwrite
= 0;
2677 sfi
.rename_information
.in
.root_fid
= 0;
2678 sfi
.rename_information
.in
.new_name
= fname2
+strlen(BASEDIR
)+1;
2680 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
2681 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2683 torture_wait_for_oplock_break(tctx
);
2684 CHECK_VAL(break_info
.failures
, 0);
2686 if (TARGET_IS_WINXP(tctx
)) {
2687 /* Win XP breaks to level2. */
2688 CHECK_VAL(break_info
.count
, 1);
2689 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2690 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2691 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2692 /* Win2K3/2k8 incorrectly doesn't break at all. */
2693 CHECK_VAL(break_info
.count
, 0);
2695 /* win7/2k8r2 break to none. */
2696 CHECK_VAL(break_info
.count
, 1);
2697 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
2701 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2702 qfi
.generic
.in
.file
.fnum
= fnum
;
2704 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2705 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2706 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname2
);
2708 torture_comment(tctx
, "open a file with the new name an batch oplock (share mode: all)\n");
2709 ZERO_STRUCT(break_info
);
2710 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2711 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2712 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2713 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2714 NTCREATEX_SHARE_ACCESS_WRITE
|
2715 NTCREATEX_SHARE_ACCESS_DELETE
;
2716 io
.ntcreatex
.in
.fname
= fname2
;
2717 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
2718 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2719 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2720 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
2722 torture_wait_for_oplock_break(tctx
);
2724 if (TARGET_IS_WINXP(tctx
)) {
2725 /* XP broke to level2, and doesn't break again. */
2726 CHECK_VAL(break_info
.count
, 0);
2727 } else if (TARGET_IS_W2K3(tctx
) || TARGET_IS_W2K8(tctx
) ||
2728 TARGET_IS_SAMBA3(tctx
) || TARGET_IS_SAMBA4(tctx
)) {
2729 /* Win2K3 incorrectly didn't break before so break now. */
2730 CHECK_VAL(break_info
.count
, 1);
2731 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2733 /* win7/2k8r2 broke to none, and doesn't break again. */
2734 CHECK_VAL(break_info
.count
, 0);
2737 ZERO_STRUCT(break_info
);
2740 sfi
.generic
.level
= RAW_SFILEINFO_RENAME_INFORMATION
;
2741 sfi
.generic
.in
.file
.fnum
= fnum
;
2742 sfi
.rename_information
.in
.overwrite
= 0;
2743 sfi
.rename_information
.in
.root_fid
= 0;
2744 sfi
.rename_information
.in
.new_name
= fname3
+strlen(BASEDIR
)+1;
2746 status
= smb_raw_setfileinfo(cli1
->tree
, &sfi
);
2747 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2749 torture_wait_for_oplock_break(tctx
);
2750 CHECK_VAL(break_info
.count
, 0);
2753 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2754 qfi
.generic
.in
.file
.fnum
= fnum
;
2756 status
= smb_raw_fileinfo(cli1
->tree
, tctx
, &qfi
);
2757 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2758 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2761 qfi
.generic
.level
= RAW_FILEINFO_ALL_INFORMATION
;
2762 qfi
.generic
.in
.file
.fnum
= fnum2
;
2764 status
= smb_raw_fileinfo(cli2
->tree
, tctx
, &qfi
);
2765 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2766 CHECK_STRMATCH(qfi
.all_info
.out
.fname
.s
, fname3
);
2770 smbcli_close(cli1
->tree
, fnum
);
2771 smbcli_close(cli2
->tree
, fnum2
);
2772 smb_raw_exit(cli1
->session
);
2773 smb_raw_exit(cli2
->session
);
2774 smbcli_deltree(cli1
->tree
, BASEDIR
);
2778 static bool test_raw_oplock_batch21(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2780 const char *fname
= BASEDIR
"\\test_batch21.dat";
2789 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2794 smbcli_unlink(cli1
->tree
, fname
);
2796 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2799 base ntcreatex parms
2801 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2802 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2803 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2804 io
.ntcreatex
.in
.alloc_size
= 0;
2805 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2806 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2807 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2808 io
.ntcreatex
.in
.create_options
= 0;
2809 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2810 io
.ntcreatex
.in
.security_flags
= 0;
2811 io
.ntcreatex
.in
.fname
= fname
;
2814 with a batch oplock we get a break
2816 torture_comment(tctx
, "BATCH21: open with batch oplock\n");
2817 ZERO_STRUCT(break_info
);
2818 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2819 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2820 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2821 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2822 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2823 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2824 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2826 torture_comment(tctx
, "writing should not generate a break\n");
2827 wr
= smbcli_write(cli1
->tree
, fnum
, 0, &c
, 0, 1);
2829 CHECK_STATUS(tctx
, smbcli_nt_error(cli1
->tree
), NT_STATUS_OK
);
2832 e
.in
.repeat_count
= 1;
2833 status
= smb_raw_echo(cli1
->transport
, &e
);
2834 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2836 torture_wait_for_oplock_break(tctx
);
2837 CHECK_VAL(break_info
.count
, 0);
2839 smbcli_close(cli1
->tree
, fnum
);
2842 smb_raw_exit(cli1
->session
);
2843 smb_raw_exit(cli2
->session
);
2844 smbcli_deltree(cli1
->tree
, BASEDIR
);
2848 static bool test_raw_oplock_batch22(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2850 const char *fname
= BASEDIR
"\\test_batch22.dat";
2854 uint16_t fnum
= 0, fnum2
= 0, fnum3
= 0;
2856 int timeout
= torture_setting_int(tctx
, "oplocktimeout", 30);
2859 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2864 smbcli_unlink(cli1
->tree
, fname
);
2866 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2868 base ntcreatex parms
2870 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2871 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2872 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2873 io
.ntcreatex
.in
.alloc_size
= 0;
2874 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2875 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
2876 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
2877 io
.ntcreatex
.in
.create_options
= 0;
2878 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
2879 io
.ntcreatex
.in
.security_flags
= 0;
2880 io
.ntcreatex
.in
.fname
= fname
;
2883 with a batch oplock we get a break
2885 torture_comment(tctx
, "BATCH22: open with batch oplock\n");
2886 ZERO_STRUCT(break_info
);
2887 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
2888 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
2889 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
2890 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
2891 NTCREATEX_SHARE_ACCESS_WRITE
|
2892 NTCREATEX_SHARE_ACCESS_DELETE
;
2893 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2894 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2895 fnum
= io
.ntcreatex
.out
.file
.fnum
;
2896 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
2898 torture_comment(tctx
, "a 2nd open should not succeed after the oplock "
2900 tv
= timeval_current();
2901 smbcli_oplock_handler(cli1
->transport
, oplock_handler_timeout
, cli1
->tree
);
2902 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2904 if (TARGET_IS_W2K3(tctx
)) {
2905 /* 2k3 has an issue here. xp/win7 are ok. */
2906 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
2908 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2911 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
2913 torture_wait_for_oplock_break(tctx
);
2914 te
= (int)timeval_elapsed(&tv
);
2917 * Some servers detect clients that let oplocks timeout, so this check
2918 * only shows a warning message instead failing the test to eliminate
2919 * failures from repeated runs of the test. This isn't ideal, but
2920 * it's better than not running the test at all.
2922 CHECK_RANGE(te
, timeout
- 1, timeout
+ 15);
2924 CHECK_VAL(break_info
.count
, 1);
2925 CHECK_VAL(break_info
.fnum
, fnum
);
2926 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
2927 CHECK_VAL(break_info
.failures
, 0);
2928 ZERO_STRUCT(break_info
);
2930 torture_comment(tctx
, "a 2nd open should succeed after the oplock "
2931 "release without break\n");
2932 tv
= timeval_current();
2933 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2934 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
2935 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
2937 /* Samba 3.6.0 and above behave as Windows. */
2938 if (TARGET_IS_SAMBA3(tctx
)) {
2939 /* samba3 doesn't grant additional oplocks to bad clients. */
2940 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
2942 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
2943 LEVEL_II_OPLOCK_RETURN
);
2946 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
2947 LEVEL_II_OPLOCK_RETURN
);
2949 torture_wait_for_oplock_break(tctx
);
2950 te
= (int)timeval_elapsed(&tv
);
2951 /* it should come in without delay */
2952 CHECK_RANGE(te
+1, 0, timeout
);
2953 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
2955 CHECK_VAL(break_info
.count
, 0);
2957 smbcli_close(cli1
->tree
, fnum
);
2958 smbcli_close(cli1
->tree
, fnum2
);
2959 smbcli_close(cli1
->tree
, fnum3
);
2962 smb_raw_exit(cli1
->session
);
2963 smb_raw_exit(cli2
->session
);
2964 smbcli_deltree(cli1
->tree
, BASEDIR
);
2968 static bool test_raw_oplock_batch23(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
2970 const char *fname
= BASEDIR
"\\test_batch23.dat";
2974 uint16_t fnum
=0, fnum2
=0,fnum3
=0;
2975 struct smbcli_state
*cli3
= NULL
;
2977 if (!torture_setup_dir(cli1
, BASEDIR
)) {
2982 smbcli_unlink(cli1
->tree
, fname
);
2984 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
2985 CHECK_VAL(ret
, true);
2987 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
2988 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
2989 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
2992 base ntcreatex parms
2994 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
2995 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
2996 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
2997 io
.ntcreatex
.in
.alloc_size
= 0;
2998 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
2999 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3000 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3001 io
.ntcreatex
.in
.create_options
= 0;
3002 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3003 io
.ntcreatex
.in
.security_flags
= 0;
3004 io
.ntcreatex
.in
.fname
= fname
;
3006 torture_comment(tctx
, "BATCH23: a open and ask for a batch oplock\n");
3007 ZERO_STRUCT(break_info
);
3009 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3010 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3011 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3012 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3013 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3014 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3015 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3016 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3017 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3019 ZERO_STRUCT(break_info
);
3021 torture_comment(tctx
, "a 2nd open without level2 oplock support should generate a break to level2\n");
3022 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3023 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3024 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3025 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3027 torture_wait_for_oplock_break(tctx
);
3028 CHECK_VAL(break_info
.count
, 1);
3029 CHECK_VAL(break_info
.fnum
, fnum
);
3030 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3031 CHECK_VAL(break_info
.failures
, 0);
3033 ZERO_STRUCT(break_info
);
3035 torture_comment(tctx
, "a 3rd open with level2 oplock support should not generate a break\n");
3036 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3037 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3038 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3039 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3041 torture_wait_for_oplock_break(tctx
);
3042 CHECK_VAL(break_info
.count
, 0);
3044 smbcli_close(cli1
->tree
, fnum
);
3045 smbcli_close(cli2
->tree
, fnum2
);
3046 smbcli_close(cli3
->tree
, fnum3
);
3049 smb_raw_exit(cli1
->session
);
3050 smb_raw_exit(cli2
->session
);
3051 smb_raw_exit(cli3
->session
);
3052 smbcli_deltree(cli1
->tree
, BASEDIR
);
3056 static bool test_raw_oplock_batch24(struct torture_context
*tctx
, struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3058 const char *fname
= BASEDIR
"\\test_batch24.dat";
3062 uint16_t fnum2
=0,fnum3
=0;
3063 struct smbcli_state
*cli3
= NULL
;
3065 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3070 smbcli_unlink(cli1
->tree
, fname
);
3072 ret
= open_connection_no_level2_oplocks(tctx
, &cli3
);
3073 CHECK_VAL(ret
, true);
3075 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3076 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3077 smbcli_oplock_handler(cli3
->transport
, oplock_handler_ack_to_given
, cli3
->tree
);
3080 base ntcreatex parms
3082 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3083 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3084 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3085 io
.ntcreatex
.in
.alloc_size
= 0;
3086 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3087 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3088 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3089 io
.ntcreatex
.in
.create_options
= 0;
3090 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3091 io
.ntcreatex
.in
.security_flags
= 0;
3092 io
.ntcreatex
.in
.fname
= fname
;
3094 torture_comment(tctx
, "BATCH24: a open without level support and ask for a batch oplock\n");
3095 ZERO_STRUCT(break_info
);
3097 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
| SEC_RIGHTS_FILE_WRITE
;
3098 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
3099 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3100 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3101 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3102 status
= smb_raw_open(cli3
->tree
, tctx
, &io
);
3103 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3104 fnum3
= io
.ntcreatex
.out
.file
.fnum
;
3105 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3107 ZERO_STRUCT(break_info
);
3109 torture_comment(tctx
, "a 2nd open with level2 oplock support should generate a break to none\n");
3110 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3111 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3112 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3113 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, LEVEL_II_OPLOCK_RETURN
);
3115 torture_wait_for_oplock_break(tctx
);
3116 CHECK_VAL(break_info
.count
, 1);
3117 CHECK_VAL(break_info
.fnum
, fnum3
);
3118 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3119 CHECK_VAL(break_info
.failures
, 0);
3121 smbcli_close(cli3
->tree
, fnum3
);
3122 smbcli_close(cli2
->tree
, fnum2
);
3125 smb_raw_exit(cli1
->session
);
3126 smb_raw_exit(cli2
->session
);
3127 smb_raw_exit(cli3
->session
);
3128 smbcli_deltree(cli1
->tree
, BASEDIR
);
3132 static bool test_raw_oplock_batch25(struct torture_context
*tctx
,
3133 struct smbcli_state
*cli1
,
3134 struct smbcli_state
*cli2
)
3136 const char *fname
= BASEDIR
"\\test_batch25.dat";
3140 union smb_setfileinfo sfi
;
3143 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3148 smbcli_unlink(cli1
->tree
, fname
);
3150 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3153 base ntcreatex parms
3155 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3156 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3157 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3158 io
.ntcreatex
.in
.alloc_size
= 0;
3159 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3160 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3161 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3162 io
.ntcreatex
.in
.create_options
= 0;
3163 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3164 io
.ntcreatex
.in
.security_flags
= 0;
3165 io
.ntcreatex
.in
.fname
= fname
;
3167 torture_comment(tctx
, "BATCH25: open a file with an batch oplock "
3168 "(share mode: none)\n");
3170 ZERO_STRUCT(break_info
);
3171 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3172 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3173 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3174 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3175 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3176 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3177 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3179 torture_comment(tctx
, "setpathinfo attribute info should not trigger "
3180 "a break nor a violation\n");
3182 sfi
.generic
.level
= RAW_SFILEINFO_SETATTR
;
3183 sfi
.generic
.in
.file
.path
= fname
;
3184 sfi
.setattr
.in
.attrib
= FILE_ATTRIBUTE_HIDDEN
;
3185 sfi
.setattr
.in
.write_time
= 0;
3187 status
= smb_raw_setpathinfo(cli2
->tree
, &sfi
);
3188 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3190 torture_wait_for_oplock_break(tctx
);
3191 CHECK_VAL(break_info
.count
, 0);
3193 smbcli_close(cli1
->tree
, fnum
);
3196 smb_raw_exit(cli1
->session
);
3197 smb_raw_exit(cli2
->session
);
3198 smbcli_deltree(cli1
->tree
, BASEDIR
);
3203 * Similar to batch17/18, but test with open share mode rather than
3206 static bool test_raw_oplock_batch26(struct torture_context
*tctx
,
3207 struct smbcli_state
*cli1
, struct smbcli_state
*cli2
)
3209 const char *fname1
= BASEDIR
"\\test_batch26_1.dat";
3210 const char *fname2
= BASEDIR
"\\test_batch26_2.dat";
3214 union smb_rename rn
;
3217 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3222 smbcli_unlink(cli1
->tree
, fname1
);
3223 smbcli_unlink(cli1
->tree
, fname2
);
3225 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3229 base ntcreatex parms
3231 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3232 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3233 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3234 io
.ntcreatex
.in
.alloc_size
= 0;
3235 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3236 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3237 NTCREATEX_SHARE_ACCESS_WRITE
| NTCREATEX_SHARE_ACCESS_DELETE
;
3238 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3239 io
.ntcreatex
.in
.create_options
= 0;
3240 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3241 io
.ntcreatex
.in
.security_flags
= 0;
3242 io
.ntcreatex
.in
.fname
= fname1
;
3244 torture_comment(tctx
, "BATCH26: open a file with an batch oplock "
3245 "(share mode: none)\n");
3247 ZERO_STRUCT(break_info
);
3248 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3249 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3250 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3253 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3254 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3255 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3256 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3258 torture_comment(tctx
, "rename should trigger a break\n");
3260 rn
.generic
.level
= RAW_RENAME_RENAME
;
3261 rn
.rename
.in
.pattern1
= fname1
;
3262 rn
.rename
.in
.pattern2
= fname2
;
3263 rn
.rename
.in
.attrib
= 0;
3265 torture_comment(tctx
, "trying rename while first file open\n");
3266 status
= smb_raw_rename(cli2
->tree
, &rn
);
3267 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3269 torture_wait_for_oplock_break(tctx
);
3270 CHECK_VAL(break_info
.count
, 1);
3271 CHECK_VAL(break_info
.failures
, 0);
3272 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3274 /* Close and reopen with batch again. */
3275 smbcli_close(cli1
->tree
, fnum
);
3276 ZERO_STRUCT(break_info
);
3278 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3279 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3280 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3281 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3283 /* Now try ntrename. */
3284 torture_comment(tctx
, "ntrename should trigger a break\n");
3286 rn
.generic
.level
= RAW_RENAME_NTRENAME
;
3287 rn
.ntrename
.in
.attrib
= 0;
3288 rn
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
3289 rn
.ntrename
.in
.old_name
= fname1
;
3290 rn
.ntrename
.in
.new_name
= fname2
;
3291 torture_comment(tctx
, "trying rename while first file open\n");
3292 status
= smb_raw_rename(cli2
->tree
, &rn
);
3293 CHECK_STATUS(tctx
, status
, NT_STATUS_SHARING_VIOLATION
);
3295 torture_wait_for_oplock_break(tctx
);
3296 CHECK_VAL(break_info
.count
, 1);
3297 CHECK_VAL(break_info
.failures
, 0);
3298 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3300 smbcli_close(cli1
->tree
, fnum
);
3303 smb_raw_exit(cli1
->session
);
3304 smb_raw_exit(cli2
->session
);
3305 smbcli_deltree(cli1
->tree
, BASEDIR
);
3309 /* Test how oplocks work on streams. */
3310 static bool test_raw_oplock_stream1(struct torture_context
*tctx
,
3311 struct smbcli_state
*cli1
,
3312 struct smbcli_state
*cli2
)
3316 const char *fname_base
= BASEDIR
"\\test_stream1.txt";
3317 const char *stream
= "Stream One:$DATA";
3318 const char *fname_stream
, *fname_default_stream
;
3319 const char *default_stream
= "::$DATA";
3323 int stream_fnum
= -1;
3324 uint32_t batch_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3325 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
| NTCREATEX_FLAGS_EXTENDED
;
3326 uint32_t exclusive_req
= NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3327 NTCREATEX_FLAGS_EXTENDED
;
3329 #define NSTREAM_OPLOCK_RESULTS 8
3332 bool open_base_file
;
3333 uint32_t oplock_req
;
3334 uint32_t oplock_granted
;
3335 } stream_oplock_results
[NSTREAM_OPLOCK_RESULTS
] = {
3336 /* Request oplock on stream without the base file open. */
3337 {&fname_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3338 {&fname_default_stream
, false, batch_req
, NO_OPLOCK_RETURN
},
3339 {&fname_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3340 {&fname_default_stream
, false, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3342 /* Request oplock on stream with the base file open. */
3343 {&fname_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3344 {&fname_default_stream
, true, batch_req
, NO_OPLOCK_RETURN
},
3345 {&fname_stream
, true, exclusive_req
, EXCLUSIVE_OPLOCK_RETURN
},
3346 {&fname_default_stream
, true, exclusive_req
, LEVEL_II_OPLOCK_RETURN
},
3351 /* Only passes against windows at the moment. */
3352 if (torture_setting_bool(tctx
, "samba3", false) ||
3353 torture_setting_bool(tctx
, "samba4", false)) {
3354 torture_skip(tctx
, "STREAM1 disabled against samba3+4\n");
3357 fname_stream
= talloc_asprintf(tctx
, "%s:%s", fname_base
, stream
);
3358 fname_default_stream
= talloc_asprintf(tctx
, "%s%s", fname_base
,
3361 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3364 smbcli_unlink(cli1
->tree
, fname_base
);
3366 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
, cli1
->tree
);
3367 smbcli_oplock_handler(cli2
->transport
, oplock_handler_ack_to_given
, cli2
->tree
);
3369 /* Setup generic open parameters. */
3370 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3371 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3372 io
.ntcreatex
.in
.access_mask
= (SEC_FILE_READ_DATA
|SEC_FILE_WRITE_DATA
|
3373 SEC_FILE_APPEND_DATA
|SEC_STD_READ_CONTROL
);
3374 io
.ntcreatex
.in
.create_options
= 0;
3375 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3376 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3377 NTCREATEX_SHARE_ACCESS_WRITE
;
3378 io
.ntcreatex
.in
.alloc_size
= 0;
3379 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3380 io
.ntcreatex
.in
.security_flags
= 0;
3382 /* Create the file with a stream */
3383 io
.ntcreatex
.in
.fname
= fname_stream
;
3384 io
.ntcreatex
.in
.flags
= 0;
3385 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
3386 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3387 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3388 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3390 /* Change the disposition to open now that the file has been created. */
3391 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
3393 /* Try some permutations of taking oplocks on streams. */
3394 for (i
= 0; i
< NSTREAM_OPLOCK_RESULTS
; i
++) {
3395 const char *fname
= *stream_oplock_results
[i
].fname
;
3396 bool open_base_file
= stream_oplock_results
[i
].open_base_file
;
3397 uint32_t oplock_req
= stream_oplock_results
[i
].oplock_req
;
3398 uint32_t oplock_granted
=
3399 stream_oplock_results
[i
].oplock_granted
;
3402 if (open_base_file
) {
3403 torture_comment(tctx
, "Opening base file: %s with "
3404 "%d\n", fname_base
, batch_req
);
3405 io
.ntcreatex
.in
.fname
= fname_base
;
3406 io
.ntcreatex
.in
.flags
= batch_req
;
3407 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3408 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3409 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3410 BATCH_OPLOCK_RETURN
);
3411 base_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3414 torture_comment(tctx
, "%d: Opening stream: %s with %d\n", i
,
3416 io
.ntcreatex
.in
.fname
= fname
;
3417 io
.ntcreatex
.in
.flags
= oplock_req
;
3419 /* Do the open with the desired oplock on the stream. */
3420 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3421 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3422 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, oplock_granted
);
3423 smbcli_close(cli1
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3425 /* Cleanup the base file if it was opened. */
3426 if (base_fnum
!= -1) {
3427 smbcli_close(cli2
->tree
, base_fnum
);
3431 /* Open the stream with an exclusive oplock. */
3432 torture_comment(tctx
, "Opening stream: %s with %d\n",
3433 fname_stream
, exclusive_req
);
3434 io
.ntcreatex
.in
.fname
= fname_stream
;
3435 io
.ntcreatex
.in
.flags
= exclusive_req
;
3436 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3437 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3438 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3439 stream_fnum
= io
.ntcreatex
.out
.file
.fnum
;
3441 /* Open the base file and see if it contends. */
3442 ZERO_STRUCT(break_info
);
3443 torture_comment(tctx
, "Opening base file: %s with "
3444 "%d\n", fname_base
, batch_req
);
3445 io
.ntcreatex
.in
.fname
= fname_base
;
3446 io
.ntcreatex
.in
.flags
= batch_req
;
3447 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3448 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3449 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3450 BATCH_OPLOCK_RETURN
);
3451 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3453 torture_wait_for_oplock_break(tctx
);
3454 CHECK_VAL(break_info
.count
, 0);
3455 CHECK_VAL(break_info
.failures
, 0);
3457 /* Open the stream again to see if it contends. */
3458 ZERO_STRUCT(break_info
);
3459 torture_comment(tctx
, "Opening stream again: %s with "
3460 "%d\n", fname_base
, batch_req
);
3461 io
.ntcreatex
.in
.fname
= fname_stream
;
3462 io
.ntcreatex
.in
.flags
= exclusive_req
;
3463 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3464 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3465 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
,
3466 LEVEL_II_OPLOCK_RETURN
);
3467 smbcli_close(cli2
->tree
, io
.ntcreatex
.out
.file
.fnum
);
3469 torture_wait_for_oplock_break(tctx
);
3470 CHECK_VAL(break_info
.count
, 1);
3471 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3472 CHECK_VAL(break_info
.failures
, 0);
3474 /* Close the stream. */
3475 if (stream_fnum
!= -1) {
3476 smbcli_close(cli1
->tree
, stream_fnum
);
3480 smbcli_close(cli1
->tree
, fnum
);
3481 smb_raw_exit(cli1
->session
);
3482 smb_raw_exit(cli2
->session
);
3483 smbcli_deltree(cli1
->tree
, BASEDIR
);
3487 static bool test_raw_oplock_doc(struct torture_context
*tctx
,
3488 struct smbcli_state
*cli
)
3490 const char *fname
= BASEDIR
"\\test_oplock_doc.dat";
3496 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
3499 smbcli_unlink(cli
->tree
, fname
);
3501 smbcli_oplock_handler(cli
->transport
, oplock_handler_ack_to_given
,
3505 base ntcreatex parms
3507 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3508 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3509 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
3510 io
.ntcreatex
.in
.alloc_size
= 0;
3511 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3512 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
3513 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3514 io
.ntcreatex
.in
.create_options
= NTCREATEX_OPTIONS_DELETE_ON_CLOSE
;
3515 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3516 io
.ntcreatex
.in
.security_flags
= 0;
3517 io
.ntcreatex
.in
.fname
= fname
;
3519 torture_comment(tctx
, "open a delete-on-close file with a batch "
3521 ZERO_STRUCT(break_info
);
3522 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3523 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3524 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3526 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
3527 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3528 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3529 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3531 smbcli_close(cli
->tree
, fnum
);
3534 smb_raw_exit(cli
->session
);
3535 smbcli_deltree(cli
->tree
, BASEDIR
);
3539 /* Open a file with a batch oplock, then open it again from a second client
3540 * requesting no oplock. Having two open file handles should break our own
3541 * oplock during BRL acquisition.
3543 static bool test_raw_oplock_brl1(struct torture_context
*tctx
,
3544 struct smbcli_state
*cli1
,
3545 struct smbcli_state
*cli2
)
3547 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3556 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3561 smbcli_unlink(cli1
->tree
, fname
);
3563 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3567 base ntcreatex parms
3569 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3570 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3571 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3572 SEC_RIGHTS_FILE_WRITE
;
3573 io
.ntcreatex
.in
.alloc_size
= 0;
3574 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3575 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3576 NTCREATEX_SHARE_ACCESS_WRITE
;
3577 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3578 io
.ntcreatex
.in
.create_options
= 0;
3579 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3580 io
.ntcreatex
.in
.security_flags
= 0;
3581 io
.ntcreatex
.in
.fname
= fname
;
3584 with a batch oplock we get a break
3586 torture_comment(tctx
, "open with batch oplock\n");
3587 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3588 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3589 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3591 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3592 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3593 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3594 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3595 /* create a file with bogus data */
3596 memset(buf
, 0, sizeof(buf
));
3598 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3601 torture_comment(tctx
, "Failed to create file\n");
3605 torture_comment(tctx
, "a 2nd open should give a break\n");
3606 ZERO_STRUCT(break_info
);
3608 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3609 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3610 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3611 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3612 CHECK_VAL(break_info
.count
, 1);
3613 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3614 CHECK_VAL(break_info
.failures
, 0);
3615 CHECK_VAL(break_info
.fnum
, fnum
);
3617 ZERO_STRUCT(break_info
);
3619 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3621 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3622 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3624 torture_wait_for_oplock_break(tctx
);
3625 CHECK_VAL(break_info
.count
, 1);
3626 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3627 CHECK_VAL(break_info
.fnum
, fnum
);
3628 CHECK_VAL(break_info
.failures
, 0);
3630 /* expect no oplock break */
3631 ZERO_STRUCT(break_info
);
3632 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3633 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3635 torture_wait_for_oplock_break(tctx
);
3636 CHECK_VAL(break_info
.count
, 0);
3637 CHECK_VAL(break_info
.level
, 0);
3638 CHECK_VAL(break_info
.fnum
, 0);
3639 CHECK_VAL(break_info
.failures
, 0);
3641 smbcli_close(cli1
->tree
, fnum
);
3642 smbcli_close(cli2
->tree
, fnum2
);
3645 smb_raw_exit(cli1
->session
);
3646 smb_raw_exit(cli2
->session
);
3647 smbcli_deltree(cli1
->tree
, BASEDIR
);
3652 /* Open a file with a batch oplock on one client and then acquire a brl.
3653 * We should not contend our own oplock.
3655 static bool test_raw_oplock_brl2(struct torture_context
*tctx
, struct smbcli_state
*cli1
)
3657 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3665 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3670 smbcli_unlink(cli1
->tree
, fname
);
3672 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3676 base ntcreatex parms
3678 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3679 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3680 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3681 SEC_RIGHTS_FILE_WRITE
;
3682 io
.ntcreatex
.in
.alloc_size
= 0;
3683 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3684 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3685 NTCREATEX_SHARE_ACCESS_WRITE
;
3686 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3687 io
.ntcreatex
.in
.create_options
= 0;
3688 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3689 io
.ntcreatex
.in
.security_flags
= 0;
3690 io
.ntcreatex
.in
.fname
= fname
;
3693 with a batch oplock we get a break
3695 torture_comment(tctx
, "open with batch oplock\n");
3696 ZERO_STRUCT(break_info
);
3697 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3698 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3699 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3701 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3702 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3703 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3704 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3706 /* create a file with bogus data */
3707 memset(buf
, 0, sizeof(buf
));
3709 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3712 torture_comment(tctx
, "Failed to create file\n");
3716 torture_comment(tctx
, "a self BRL acquisition should not break to "
3719 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3720 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3722 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3723 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3725 /* With one file handle open a BRL should not contend our oplock.
3726 * Thus, no oplock break will be received and the entire break_info
3727 * struct will be 0 */
3728 torture_wait_for_oplock_break(tctx
);
3729 CHECK_VAL(break_info
.fnum
, 0);
3730 CHECK_VAL(break_info
.count
, 0);
3731 CHECK_VAL(break_info
.level
, 0);
3732 CHECK_VAL(break_info
.failures
, 0);
3734 smbcli_close(cli1
->tree
, fnum
);
3737 smb_raw_exit(cli1
->session
);
3738 smbcli_deltree(cli1
->tree
, BASEDIR
);
3742 /* Open a file with a batch oplock twice from one client and then acquire a
3743 * brl. BRL acquisition should break our own oplock.
3745 static bool test_raw_oplock_brl3(struct torture_context
*tctx
,
3746 struct smbcli_state
*cli1
)
3748 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3751 bool correct
= true;
3757 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3762 smbcli_unlink(cli1
->tree
, fname
);
3764 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3768 base ntcreatex parms
3770 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3771 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3772 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3773 SEC_RIGHTS_FILE_WRITE
;
3774 io
.ntcreatex
.in
.alloc_size
= 0;
3775 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3776 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3777 NTCREATEX_SHARE_ACCESS_WRITE
;
3778 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3779 io
.ntcreatex
.in
.create_options
= 0;
3780 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3781 io
.ntcreatex
.in
.security_flags
= 0;
3782 io
.ntcreatex
.in
.fname
= fname
;
3785 with a batch oplock we get a break
3787 torture_comment(tctx
, "open with batch oplock\n");
3788 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3789 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
3790 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
3792 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3793 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3794 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3795 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, BATCH_OPLOCK_RETURN
);
3797 /* create a file with bogus data */
3798 memset(buf
, 0, sizeof(buf
));
3800 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3803 torture_comment(tctx
, "Failed to create file\n");
3808 torture_comment(tctx
, "a 2nd open should give a break\n");
3809 ZERO_STRUCT(break_info
);
3811 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
3812 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3813 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3814 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3815 CHECK_VAL(break_info
.count
, 1);
3816 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3817 CHECK_VAL(break_info
.failures
, 0);
3818 CHECK_VAL(break_info
.fnum
, fnum
);
3820 ZERO_STRUCT(break_info
);
3822 torture_comment(tctx
, "a self BRL acquisition should break to none\n");
3824 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 4, 0, WRITE_LOCK
);
3825 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3827 torture_wait_for_oplock_break(tctx
);
3828 CHECK_VAL(break_info
.count
, 1);
3829 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_NONE
);
3830 CHECK_VAL(break_info
.fnum
, fnum
);
3831 CHECK_VAL(break_info
.failures
, 0);
3833 /* expect no oplock break */
3834 ZERO_STRUCT(break_info
);
3835 status
= smbcli_lock(cli1
->tree
, fnum
, 2, 4, 0, WRITE_LOCK
);
3836 CHECK_STATUS(tctx
, status
, NT_STATUS_LOCK_NOT_GRANTED
);
3838 torture_wait_for_oplock_break(tctx
);
3839 CHECK_VAL(break_info
.count
, 0);
3840 CHECK_VAL(break_info
.level
, 0);
3841 CHECK_VAL(break_info
.fnum
, 0);
3842 CHECK_VAL(break_info
.failures
, 0);
3844 smbcli_close(cli1
->tree
, fnum
);
3845 smbcli_close(cli1
->tree
, fnum2
);
3848 smb_raw_exit(cli1
->session
);
3849 smbcli_deltree(cli1
->tree
, BASEDIR
);
3854 * Open a file with an exclusive oplock from the 1st client and acquire a
3855 * brl. Then open the same file from the 2nd client that should give oplock
3856 * break with level2 to the 1st and return no oplock to the 2nd.
3858 static bool test_raw_oplock_brl4(struct torture_context
*tctx
,
3859 struct smbcli_state
*cli1
,
3860 struct smbcli_state
*cli2
)
3862 const char *fname
= BASEDIR
"\\test_batch_brl.dat";
3870 if (!torture_setup_dir(cli1
, BASEDIR
)) {
3875 smbcli_unlink(cli1
->tree
, fname
);
3877 smbcli_oplock_handler(cli1
->transport
, oplock_handler_ack_to_given
,
3881 base ntcreatex parms
3883 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
3884 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
3885 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_READ
|
3886 SEC_RIGHTS_FILE_WRITE
;
3887 io
.ntcreatex
.in
.alloc_size
= 0;
3888 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
3889 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
3890 NTCREATEX_SHARE_ACCESS_WRITE
;
3891 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
3892 io
.ntcreatex
.in
.create_options
= 0;
3893 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
3894 io
.ntcreatex
.in
.security_flags
= 0;
3895 io
.ntcreatex
.in
.fname
= fname
;
3897 torture_comment(tctx
, "open with exclusive oplock\n");
3898 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
3899 NTCREATEX_FLAGS_REQUEST_OPLOCK
;
3901 status
= smb_raw_open(cli1
->tree
, tctx
, &io
);
3903 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3904 fnum
= io
.ntcreatex
.out
.file
.fnum
;
3905 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, EXCLUSIVE_OPLOCK_RETURN
);
3907 /* create a file with bogus data */
3908 memset(buf
, 0, sizeof(buf
));
3910 if (smbcli_write(cli1
->tree
, fnum
, 0, buf
, 0, sizeof(buf
)) !=
3913 torture_comment(tctx
, "Failed to create file\n");
3917 status
= smbcli_lock(cli1
->tree
, fnum
, 0, 1, 0, WRITE_LOCK
);
3918 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3920 torture_comment(tctx
, "a 2nd open should give a break to the 1st\n");
3921 ZERO_STRUCT(break_info
);
3923 status
= smb_raw_open(cli2
->tree
, tctx
, &io
);
3925 CHECK_STATUS(tctx
, status
, NT_STATUS_OK
);
3926 CHECK_VAL(break_info
.count
, 1);
3927 CHECK_VAL(break_info
.level
, OPLOCK_BREAK_TO_LEVEL_II
);
3928 CHECK_VAL(break_info
.failures
, 0);
3929 CHECK_VAL(break_info
.fnum
, fnum
);
3931 torture_comment(tctx
, "and return no oplock to the 2nd\n");
3932 fnum2
= io
.ntcreatex
.out
.file
.fnum
;
3933 CHECK_VAL(io
.ntcreatex
.out
.oplock_level
, NO_OPLOCK_RETURN
);
3935 smbcli_close(cli1
->tree
, fnum
);
3936 smbcli_close(cli2
->tree
, fnum2
);
3939 smb_raw_exit(cli1
->session
);
3940 smb_raw_exit(cli2
->session
);
3941 smbcli_deltree(cli1
->tree
, BASEDIR
);
3946 basic testing of oplocks
3948 struct torture_suite
*torture_raw_oplock(TALLOC_CTX
*mem_ctx
)
3950 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "oplock");
3952 torture_suite_add_2smb_test(suite
, "exclusive1", test_raw_oplock_exclusive1
);
3953 torture_suite_add_2smb_test(suite
, "exclusive2", test_raw_oplock_exclusive2
);
3954 torture_suite_add_2smb_test(suite
, "exclusive3", test_raw_oplock_exclusive3
);
3955 torture_suite_add_2smb_test(suite
, "exclusive4", test_raw_oplock_exclusive4
);
3956 torture_suite_add_2smb_test(suite
, "exclusive5", test_raw_oplock_exclusive5
);
3957 torture_suite_add_2smb_test(suite
, "exclusive6", test_raw_oplock_exclusive6
);
3958 torture_suite_add_2smb_test(suite
, "exclusive7", test_raw_oplock_exclusive7
);
3959 torture_suite_add_2smb_test(suite
, "batch1", test_raw_oplock_batch1
);
3960 torture_suite_add_2smb_test(suite
, "batch2", test_raw_oplock_batch2
);
3961 torture_suite_add_2smb_test(suite
, "batch3", test_raw_oplock_batch3
);
3962 torture_suite_add_2smb_test(suite
, "batch4", test_raw_oplock_batch4
);
3963 torture_suite_add_2smb_test(suite
, "batch5", test_raw_oplock_batch5
);
3964 torture_suite_add_2smb_test(suite
, "batch6", test_raw_oplock_batch6
);
3965 torture_suite_add_2smb_test(suite
, "batch7", test_raw_oplock_batch7
);
3966 torture_suite_add_2smb_test(suite
, "batch8", test_raw_oplock_batch8
);
3967 torture_suite_add_2smb_test(suite
, "batch9", test_raw_oplock_batch9
);
3968 torture_suite_add_2smb_test(suite
, "batch10", test_raw_oplock_batch10
);
3969 torture_suite_add_2smb_test(suite
, "batch11", test_raw_oplock_batch11
);
3970 torture_suite_add_2smb_test(suite
, "batch12", test_raw_oplock_batch12
);
3971 torture_suite_add_2smb_test(suite
, "batch13", test_raw_oplock_batch13
);
3972 torture_suite_add_2smb_test(suite
, "batch14", test_raw_oplock_batch14
);
3973 torture_suite_add_2smb_test(suite
, "batch15", test_raw_oplock_batch15
);
3974 torture_suite_add_2smb_test(suite
, "batch16", test_raw_oplock_batch16
);
3975 torture_suite_add_2smb_test(suite
, "batch17", test_raw_oplock_batch17
);
3976 torture_suite_add_2smb_test(suite
, "batch18", test_raw_oplock_batch18
);
3977 torture_suite_add_2smb_test(suite
, "batch19", test_raw_oplock_batch19
);
3978 torture_suite_add_2smb_test(suite
, "batch20", test_raw_oplock_batch20
);
3979 torture_suite_add_2smb_test(suite
, "batch21", test_raw_oplock_batch21
);
3980 torture_suite_add_2smb_test(suite
, "batch22", test_raw_oplock_batch22
);
3981 torture_suite_add_2smb_test(suite
, "batch23", test_raw_oplock_batch23
);
3982 torture_suite_add_2smb_test(suite
, "batch24", test_raw_oplock_batch24
);
3983 torture_suite_add_2smb_test(suite
, "batch25", test_raw_oplock_batch25
);
3984 torture_suite_add_2smb_test(suite
, "batch26", test_raw_oplock_batch26
);
3985 torture_suite_add_2smb_test(suite
, "stream1", test_raw_oplock_stream1
);
3986 torture_suite_add_1smb_test(suite
, "doc1", test_raw_oplock_doc
);
3987 torture_suite_add_2smb_test(suite
, "brl1", test_raw_oplock_brl1
);
3988 torture_suite_add_1smb_test(suite
, "brl2", test_raw_oplock_brl2
);
3989 torture_suite_add_1smb_test(suite
, "brl3", test_raw_oplock_brl3
);
3990 torture_suite_add_2smb_test(suite
, "brl4", test_raw_oplock_brl4
);
3996 stress testing of oplocks
3998 bool torture_bench_oplock(struct torture_context
*torture
)
4000 struct smbcli_state
**cli
;
4002 TALLOC_CTX
*mem_ctx
= talloc_new(torture
);
4003 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
4005 int timelimit
= torture_setting_int(torture
, "timelimit", 10);
4009 cli
= talloc_array(mem_ctx
, struct smbcli_state
*, torture_nprocs
);
4011 torture_comment(torture
, "Opening %d connections\n", torture_nprocs
);
4012 for (i
=0;i
<torture_nprocs
;i
++) {
4013 if (!torture_open_connection_ev(&cli
[i
], i
, torture
, torture
->ev
)) {
4016 talloc_steal(mem_ctx
, cli
[i
]);
4017 smbcli_oplock_handler(cli
[i
]->transport
, oplock_handler_close
,
4021 if (!torture_setup_dir(cli
[0], BASEDIR
)) {
4026 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
4027 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4028 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4029 io
.ntcreatex
.in
.alloc_size
= 0;
4030 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4031 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
4032 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4033 io
.ntcreatex
.in
.create_options
= 0;
4034 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4035 io
.ntcreatex
.in
.security_flags
= 0;
4036 io
.ntcreatex
.in
.fname
= BASEDIR
"\\test.dat";
4037 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4038 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4039 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4041 tv
= timeval_current();
4044 we open the same file with SHARE_ACCESS_NONE from all the
4045 connections in a round robin fashion. Each open causes an
4046 oplock break on the previous connection, which is answered
4047 by the oplock_handler_close() to close the file.
4049 This measures how fast we can pass on oplocks, and stresses
4050 the oplock handling code
4052 torture_comment(torture
, "Running for %d seconds\n", timelimit
);
4053 while (timeval_elapsed(&tv
) < timelimit
) {
4054 for (i
=0;i
<torture_nprocs
;i
++) {
4057 status
= smb_raw_open(cli
[i
]->tree
, mem_ctx
, &io
);
4058 CHECK_STATUS(torture
, status
, NT_STATUS_OK
);
4062 if (torture_setting_bool(torture
, "progress", true)) {
4063 torture_comment(torture
, "%.2f ops/second\r", count
/timeval_elapsed(&tv
));
4067 torture_comment(torture
, "%.2f ops/second\n", count
/timeval_elapsed(&tv
));
4069 smb_raw_exit(cli
[torture_nprocs
-1]->session
);
4072 smb_raw_exit(cli
[0]->session
);
4073 smbcli_deltree(cli
[0]->tree
, BASEDIR
);
4074 talloc_free(mem_ctx
);
4079 static struct hold_oplock_info
{
4081 bool close_on_break
;
4082 uint32_t share_access
;
4085 { BASEDIR
"\\notshared_close", true,
4086 NTCREATEX_SHARE_ACCESS_NONE
, },
4087 { BASEDIR
"\\notshared_noclose", false,
4088 NTCREATEX_SHARE_ACCESS_NONE
, },
4089 { BASEDIR
"\\shared_close", true,
4090 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4091 { BASEDIR
"\\shared_noclose", false,
4092 NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
|NTCREATEX_SHARE_ACCESS_DELETE
, },
4095 static bool oplock_handler_hold(struct smbcli_transport
*transport
,
4096 uint16_t tid
, uint16_t fnum
, uint8_t level
,
4099 struct smbcli_tree
*tree
= (struct smbcli_tree
*)private_data
;
4100 struct hold_oplock_info
*info
;
4103 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4104 if (hold_info
[i
].fnum
== fnum
) break;
4107 if (i
== ARRAY_SIZE(hold_info
)) {
4108 printf("oplock break for unknown fnum %u\n", fnum
);
4112 info
= &hold_info
[i
];
4114 if (info
->close_on_break
) {
4115 printf("oplock break on %s - closing\n",
4117 oplock_handler_close(transport
, tid
, fnum
, level
, private_data
);
4121 printf("oplock break on %s - acking break\n", info
->fname
);
4123 return smbcli_oplock_ack(tree
, fnum
, OPLOCK_BREAK_TO_NONE
);
4128 used for manual testing of oplocks - especially interaction with
4129 other filesystems (such as NFS and local access)
4131 bool torture_hold_oplock(struct torture_context
*torture
,
4132 struct smbcli_state
*cli
)
4134 struct tevent_context
*ev
= torture
->ev
;
4137 printf("Setting up open files with oplocks in %s\n", BASEDIR
);
4139 torture_assert(torture
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
4141 smbcli_oplock_handler(cli
->transport
, oplock_handler_hold
, cli
->tree
);
4143 /* setup the files */
4144 for (i
=0;i
<ARRAY_SIZE(hold_info
);i
++) {
4149 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
4150 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
4151 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
4152 io
.ntcreatex
.in
.alloc_size
= 0;
4153 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
4154 io
.ntcreatex
.in
.share_access
= hold_info
[i
].share_access
;
4155 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
4156 io
.ntcreatex
.in
.create_options
= 0;
4157 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
4158 io
.ntcreatex
.in
.security_flags
= 0;
4159 io
.ntcreatex
.in
.fname
= hold_info
[i
].fname
;
4160 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
|
4161 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
4162 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
4163 printf("opening %s\n", hold_info
[i
].fname
);
4165 status
= smb_raw_open(cli
->tree
, cli
, &io
);
4166 if (!NT_STATUS_IS_OK(status
)) {
4167 printf("Failed to open %s - %s\n",
4168 hold_info
[i
].fname
, nt_errstr(status
));
4172 if (io
.ntcreatex
.out
.oplock_level
!= BATCH_OPLOCK_RETURN
) {
4173 printf("Oplock not granted for %s - expected %d but got %d\n",
4174 hold_info
[i
].fname
, BATCH_OPLOCK_RETURN
,
4175 io
.ntcreatex
.out
.oplock_level
);
4178 hold_info
[i
].fnum
= io
.ntcreatex
.out
.file
.fnum
;
4180 /* make the file non-zero size */
4181 if (smbcli_write(cli
->tree
, hold_info
[i
].fnum
, 0, &c
, 0, 1) != 1) {
4182 printf("Failed to write to file\n");
4187 printf("Waiting for oplock events\n");
4188 tevent_loop_wait(ev
);