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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "torture/torture.h"
23 #include "librpc/gen_ndr/security.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27 #include "lib/events/events.h"
29 #define CHECK_VAL(v, correct) do { \
30 if ((v) != (correct)) { \
31 printf("(%d) wrong value for %s got 0x%x - should be 0x%x\n", \
32 __LINE__, #v, (int)v, (int)correct); \
36 #define CHECK_STATUS(status, correct) do { \
37 if (!NT_STATUS_EQUAL(status, correct)) { \
38 printf("(%d) Incorrect status %s - should be %s\n", \
39 __LINE__, nt_errstr(status), nt_errstr(correct)); \
52 #define BASEDIR "\\test_notify"
55 a handler function for oplock break requests. Ack it as a break to level II if possible
57 static BOOL oplock_handler_ack_to_levelII(struct smbcli_transport *transport, uint16_t tid,
58 uint16_t fnum, uint8_t level, void *private)
60 struct smbcli_tree *tree = private;
61 break_info.fnum = fnum;
62 break_info.level = level;
65 printf("Acking to level II in oplock handler\n");
67 return smbcli_oplock_ack(tree, fnum, level);
71 a handler function for oplock break requests. Ack it as a break to none
73 static BOOL oplock_handler_ack_to_none(struct smbcli_transport *transport, uint16_t tid,
74 uint16_t fnum, uint8_t level,
77 struct smbcli_tree *tree = private;
78 break_info.fnum = fnum;
79 break_info.level = level;
82 printf("Acking to none in oplock handler\n");
84 return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
87 static void oplock_handler_close_recv(struct smbcli_request *req)
90 status = smbcli_request_simple_recv(req);
91 if (!NT_STATUS_IS_OK(status)) {
92 printf("close failed in oplock_handler_close\n");
93 break_info.failures++;
98 a handler function for oplock break requests - close the file
100 static BOOL oplock_handler_close(struct smbcli_transport *transport, uint16_t tid,
101 uint16_t fnum, uint8_t level, void *private)
104 struct smbcli_tree *tree = private;
105 struct smbcli_request *req;
107 break_info.fnum = fnum;
108 break_info.level = level;
111 io.close.level = RAW_CLOSE_CLOSE;
112 io.close.in.file.fnum = fnum;
113 io.close.in.write_time = 0;
114 req = smb_raw_close_send(tree, &io);
116 printf("failed to send close in oplock_handler_close\n");
120 req->async.fn = oplock_handler_close_recv;
121 req->async.private = NULL;
129 static BOOL test_oplock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
131 const char *fname = BASEDIR "\\test_oplock.dat";
135 union smb_unlink unl;
137 union smb_setfileinfo sfi;
138 uint16_t fnum=0, fnum2=0;
142 smbcli_unlink(cli->tree, fname);
144 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
149 io.generic.level = RAW_OPEN_NTCREATEX;
150 io.ntcreatex.in.root_fid = 0;
151 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
152 io.ntcreatex.in.alloc_size = 0;
153 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
154 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
155 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
156 io.ntcreatex.in.create_options = 0;
157 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
158 io.ntcreatex.in.security_flags = 0;
159 io.ntcreatex.in.fname = fname;
161 printf("open a file with a normal oplock\n");
162 ZERO_STRUCT(break_info);
163 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
165 status = smb_raw_open(cli->tree, mem_ctx, &io);
166 CHECK_STATUS(status, NT_STATUS_OK);
167 fnum = io.ntcreatex.out.file.fnum;
168 CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
170 printf("a 2nd open should not cause a break\n");
171 status = smb_raw_open(cli->tree, mem_ctx, &io);
172 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
173 CHECK_VAL(break_info.count, 0);
174 CHECK_VAL(break_info.failures, 0);
176 printf("unlink it - should also be no break\n");
177 unl.unlink.in.pattern = fname;
178 unl.unlink.in.attrib = 0;
179 status = smb_raw_unlink(cli->tree, &unl);
180 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
181 CHECK_VAL(break_info.count, 0);
182 CHECK_VAL(break_info.failures, 0);
184 smbcli_close(cli->tree, fnum);
187 with a batch oplock we get a break
189 printf("open with batch oplock\n");
190 ZERO_STRUCT(break_info);
191 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
192 NTCREATEX_FLAGS_REQUEST_OPLOCK |
193 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
194 status = smb_raw_open(cli->tree, mem_ctx, &io);
195 CHECK_STATUS(status, NT_STATUS_OK);
196 fnum = io.ntcreatex.out.file.fnum;
197 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
199 printf("unlink should generate a break\n");
200 unl.unlink.in.pattern = fname;
201 unl.unlink.in.attrib = 0;
202 status = smb_raw_unlink(cli->tree, &unl);
203 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
205 CHECK_VAL(break_info.count, 1);
206 CHECK_VAL(break_info.fnum, fnum);
207 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
208 CHECK_VAL(break_info.failures, 0);
210 printf("2nd unlink should not generate a break\n");
211 ZERO_STRUCT(break_info);
212 status = smb_raw_unlink(cli->tree, &unl);
213 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
215 CHECK_VAL(break_info.count, 0);
217 printf("writing should generate a self break to none\n");
218 smbcli_write(cli->tree, fnum, 0, &c, 0, 1);
220 smbcli_write(cli->tree, fnum, 0, &c, 1, 1);
222 CHECK_VAL(break_info.count, 1);
223 CHECK_VAL(break_info.fnum, fnum);
224 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_NONE);
225 CHECK_VAL(break_info.failures, 0);
227 smbcli_close(cli->tree, fnum);
230 printf("open with batch oplock\n");
231 ZERO_STRUCT(break_info);
232 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
233 NTCREATEX_FLAGS_REQUEST_OPLOCK |
234 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
235 status = smb_raw_open(cli->tree, mem_ctx, &io);
236 CHECK_STATUS(status, NT_STATUS_OK);
237 fnum = io.ntcreatex.out.file.fnum;
238 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
240 printf("unlink should generate a break, which we ack as break to none\n");
241 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_none, cli->tree);
242 unl.unlink.in.pattern = fname;
243 unl.unlink.in.attrib = 0;
244 status = smb_raw_unlink(cli->tree, &unl);
245 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
247 CHECK_VAL(break_info.count, 1);
248 CHECK_VAL(break_info.fnum, fnum);
249 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
250 CHECK_VAL(break_info.failures, 0);
252 printf("2nd unlink should not generate a break\n");
253 ZERO_STRUCT(break_info);
254 status = smb_raw_unlink(cli->tree, &unl);
255 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
257 CHECK_VAL(break_info.count, 0);
259 printf("writing should not generate a break\n");
260 smbcli_write(cli->tree, fnum, 0, &c, 0, 1);
262 smbcli_write(cli->tree, fnum, 0, &c, 1, 1);
264 CHECK_VAL(break_info.count, 0);
266 smbcli_close(cli->tree, fnum);
268 printf("if we close on break then the unlink can succeed\n");
269 ZERO_STRUCT(break_info);
270 smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
271 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
272 NTCREATEX_FLAGS_REQUEST_OPLOCK |
273 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
274 status = smb_raw_open(cli->tree, mem_ctx, &io);
275 CHECK_STATUS(status, NT_STATUS_OK);
276 fnum = io.ntcreatex.out.file.fnum;
277 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
279 unl.unlink.in.pattern = fname;
280 unl.unlink.in.attrib = 0;
281 ZERO_STRUCT(break_info);
282 status = smb_raw_unlink(cli->tree, &unl);
283 CHECK_STATUS(status, NT_STATUS_OK);
285 CHECK_VAL(break_info.count, 1);
286 CHECK_VAL(break_info.fnum, fnum);
287 CHECK_VAL(break_info.level, 1);
288 CHECK_VAL(break_info.failures, 0);
290 printf("a self read should not cause a break\n");
291 ZERO_STRUCT(break_info);
292 smbcli_close(cli->tree, fnum);
293 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
295 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
296 NTCREATEX_FLAGS_REQUEST_OPLOCK |
297 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
298 status = smb_raw_open(cli->tree, mem_ctx, &io);
299 CHECK_STATUS(status, NT_STATUS_OK);
300 fnum = io.ntcreatex.out.file.fnum;
301 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
303 rd.read.level = RAW_READ_READ;
304 rd.read.in.file.fnum = fnum;
305 rd.read.in.count = 1;
306 rd.read.in.offset = 0;
307 rd.read.in.remaining = 0;
308 status = smb_raw_read(cli->tree, &rd);
309 CHECK_STATUS(status, NT_STATUS_OK);
310 CHECK_VAL(break_info.count, 0);
311 CHECK_VAL(break_info.failures, 0);
313 printf("a 2nd open should give a break\n");
314 ZERO_STRUCT(break_info);
315 smbcli_close(cli->tree, fnum);
316 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
318 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
319 NTCREATEX_FLAGS_REQUEST_OPLOCK |
320 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
321 status = smb_raw_open(cli->tree, mem_ctx, &io);
322 CHECK_STATUS(status, NT_STATUS_OK);
323 fnum = io.ntcreatex.out.file.fnum;
324 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
326 ZERO_STRUCT(break_info);
328 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
329 status = smb_raw_open(cli->tree, mem_ctx, &io);
330 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
332 CHECK_VAL(break_info.count, 1);
333 CHECK_VAL(break_info.fnum, fnum);
334 CHECK_VAL(break_info.level, 1);
335 CHECK_VAL(break_info.failures, 0);
338 printf("a 2nd open should give a break to level II if the first open allowed shared read\n");
339 ZERO_STRUCT(break_info);
340 smbcli_close(cli->tree, fnum);
341 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
343 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE;
344 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
345 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
346 NTCREATEX_FLAGS_REQUEST_OPLOCK |
347 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
348 status = smb_raw_open(cli->tree, mem_ctx, &io);
349 CHECK_STATUS(status, NT_STATUS_OK);
350 fnum = io.ntcreatex.out.file.fnum;
351 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
353 ZERO_STRUCT(break_info);
355 status = smb_raw_open(cli->tree, mem_ctx, &io);
356 CHECK_STATUS(status, NT_STATUS_OK);
357 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
359 CHECK_VAL(break_info.count, 1);
360 CHECK_VAL(break_info.fnum, fnum);
361 CHECK_VAL(break_info.level, 1);
362 CHECK_VAL(break_info.failures, 0);
363 ZERO_STRUCT(break_info);
365 printf("write should trigger a break to none on both\n");
366 smbcli_write(cli->tree, fnum, 0, &c, 0, 1);
368 smbcli_write(cli->tree, fnum, 0, &c, 1, 1);
370 CHECK_VAL(break_info.count, 2);
371 CHECK_VAL(break_info.level, 0);
372 CHECK_VAL(break_info.failures, 0);
374 smb_raw_exit(cli->session);
376 printf("a 2nd open should get an oplock when we close instead of ack\n");
377 ZERO_STRUCT(break_info);
378 smbcli_close(cli->tree, fnum);
379 smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
381 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
382 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
383 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
384 NTCREATEX_FLAGS_REQUEST_OPLOCK |
385 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
386 status = smb_raw_open(cli->tree, mem_ctx, &io);
387 CHECK_STATUS(status, NT_STATUS_OK);
388 fnum2 = io.ntcreatex.out.file.fnum;
389 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
391 ZERO_STRUCT(break_info);
393 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
394 NTCREATEX_FLAGS_REQUEST_OPLOCK |
395 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
396 status = smb_raw_open(cli->tree, mem_ctx, &io);
397 CHECK_STATUS(status, NT_STATUS_OK);
398 fnum = io.ntcreatex.out.file.fnum;
399 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
401 CHECK_VAL(break_info.count, 1);
402 CHECK_VAL(break_info.fnum, fnum2);
403 CHECK_VAL(break_info.level, 1);
404 CHECK_VAL(break_info.failures, 0);
406 smbcli_close(cli->tree, fnum);
408 printf("open with batch oplock\n");
409 ZERO_STRUCT(break_info);
410 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
412 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
413 NTCREATEX_FLAGS_REQUEST_OPLOCK |
414 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
415 status = smb_raw_open(cli->tree, mem_ctx, &io);
416 CHECK_STATUS(status, NT_STATUS_OK);
417 fnum = io.ntcreatex.out.file.fnum;
418 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
420 ZERO_STRUCT(break_info);
421 printf("second open with attributes only shouldn't cause oplock break\n");
423 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
424 NTCREATEX_FLAGS_REQUEST_OPLOCK |
425 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
426 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
427 status = smb_raw_open(cli->tree, mem_ctx, &io);
428 CHECK_STATUS(status, NT_STATUS_OK);
429 fnum2 = io.ntcreatex.out.file.fnum;
430 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
431 CHECK_VAL(break_info.count, 0);
432 CHECK_VAL(break_info.failures, 0);
434 smbcli_close(cli->tree, fnum);
435 smbcli_close(cli->tree, fnum2);
436 smbcli_unlink(cli->tree, fname);
438 printf("open with attributes only can create file\n");
439 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
440 NTCREATEX_FLAGS_REQUEST_OPLOCK |
441 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
442 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
443 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
444 status = smb_raw_open(cli->tree, mem_ctx, &io);
445 CHECK_STATUS(status, NT_STATUS_OK);
446 fnum = io.ntcreatex.out.file.fnum;
447 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
449 printf("Subsequent normal open should break oplock on attribute only open to level II\n");
451 ZERO_STRUCT(break_info);
452 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
454 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
455 NTCREATEX_FLAGS_REQUEST_OPLOCK |
456 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
457 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
458 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
459 status = smb_raw_open(cli->tree, mem_ctx, &io);
460 CHECK_STATUS(status, NT_STATUS_OK);
461 fnum2 = io.ntcreatex.out.file.fnum;
462 CHECK_VAL(break_info.count, 1);
463 CHECK_VAL(break_info.fnum, fnum);
464 CHECK_VAL(break_info.failures, 0);
465 CHECK_VAL(break_info.level, OPLOCK_BREAK_TO_LEVEL_II);
466 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
467 smbcli_close(cli->tree, fnum2);
469 printf("third oplocked open should grant level2 without break\n");
470 ZERO_STRUCT(break_info);
471 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
472 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
473 NTCREATEX_FLAGS_REQUEST_OPLOCK |
474 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
475 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
476 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
477 status = smb_raw_open(cli->tree, mem_ctx, &io);
478 CHECK_STATUS(status, NT_STATUS_OK);
479 fnum2 = io.ntcreatex.out.file.fnum;
480 CHECK_VAL(break_info.count, 0);
481 CHECK_VAL(break_info.failures, 0);
482 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
484 ZERO_STRUCT(break_info);
486 printf("write should trigger a break to none on both\n");
487 smbcli_write(cli->tree, fnum2, 0, &c, 0, 1);
489 /* Now the oplock break request comes in. But right now we can't
490 * answer it. Do another write */
493 smbcli_write(cli->tree, fnum2, 0, &c, 1, 1);
495 CHECK_VAL(break_info.count, 2);
496 CHECK_VAL(break_info.level, 0);
497 CHECK_VAL(break_info.failures, 0);
499 smbcli_close(cli->tree, fnum);
500 smbcli_close(cli->tree, fnum2);
502 ZERO_STRUCT(break_info);
503 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
505 printf("Open with oplock after a on-oplock open should grant level2\n");
506 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
507 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
508 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
509 NTCREATEX_SHARE_ACCESS_WRITE|
510 NTCREATEX_SHARE_ACCESS_DELETE;
511 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
512 status = smb_raw_open(cli->tree, mem_ctx, &io);
513 CHECK_STATUS(status, NT_STATUS_OK);
514 fnum = io.ntcreatex.out.file.fnum;
515 CHECK_VAL(break_info.count, 0);
516 CHECK_VAL(break_info.failures, 0);
517 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
519 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
520 NTCREATEX_FLAGS_REQUEST_OPLOCK |
521 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
522 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
523 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
524 NTCREATEX_SHARE_ACCESS_WRITE|
525 NTCREATEX_SHARE_ACCESS_DELETE;
526 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
527 status = smb_raw_open(cli->tree, mem_ctx, &io);
528 CHECK_STATUS(status, NT_STATUS_OK);
529 fnum2 = io.ntcreatex.out.file.fnum;
530 CHECK_VAL(break_info.count, 0);
531 CHECK_VAL(break_info.failures, 0);
532 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
534 printf("write should trigger a break to none\n");
537 wr.write.level = RAW_WRITE_WRITE;
538 wr.write.in.file.fnum = fnum;
539 wr.write.in.count = 1;
540 wr.write.in.offset = 0;
541 wr.write.in.remaining = 0;
542 wr.write.in.data = (const uint8_t *)"x";
543 status = smb_raw_write(cli->tree, &wr);
544 CHECK_STATUS(status, NT_STATUS_OK);
547 /* Now the oplock break request comes in. But right now we can't
548 * answer it. Do another write */
554 wr.write.level = RAW_WRITE_WRITE;
555 wr.write.in.file.fnum = fnum;
556 wr.write.in.count = 1;
557 wr.write.in.offset = 0;
558 wr.write.in.remaining = 0;
559 wr.write.in.data = (const uint8_t *)"x";
560 status = smb_raw_write(cli->tree, &wr);
561 CHECK_STATUS(status, NT_STATUS_OK);
564 CHECK_VAL(break_info.count, 1);
565 CHECK_VAL(break_info.fnum, fnum2);
566 CHECK_VAL(break_info.level, 0);
567 CHECK_VAL(break_info.failures, 0);
569 smbcli_close(cli->tree, fnum);
570 smbcli_close(cli->tree, fnum2);
571 smbcli_unlink(cli->tree, fname);
573 /* Test if a set-eof on pathname breaks an exclusive oplock. */
574 printf("Test if setpathinfo breaks oplocks.\n");
576 ZERO_STRUCT(break_info);
577 smbcli_oplock_handler(cli->transport, oplock_handler_ack_to_levelII, cli->tree);
579 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
580 NTCREATEX_FLAGS_REQUEST_OPLOCK |
581 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
582 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
583 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
584 NTCREATEX_SHARE_ACCESS_WRITE|
585 NTCREATEX_SHARE_ACCESS_DELETE;
586 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
587 status = smb_raw_open(cli->tree, mem_ctx, &io);
588 CHECK_STATUS(status, NT_STATUS_OK);
589 fnum2 = io.ntcreatex.out.file.fnum;
590 CHECK_VAL(break_info.count, 0);
591 CHECK_VAL(break_info.failures, 0);
592 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
595 sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
596 sfi.generic.in.file.path = fname;
597 sfi.end_of_file_info.in.size = 100;
599 status = smb_raw_setpathinfo(cli->tree, &sfi);
601 CHECK_STATUS(status, NT_STATUS_OK);
602 CHECK_VAL(break_info.count, 1);
603 CHECK_VAL(break_info.failures, 0);
604 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
607 smbcli_close(cli->tree, fnum);
608 smbcli_close(cli->tree, fnum2);
609 smbcli_unlink(cli->tree, fname);
615 basic testing of oplocks
617 BOOL torture_raw_oplock(struct torture_context *torture)
619 struct smbcli_state *cli;
623 if (!torture_open_connection(&cli)) {
627 if (!torture_setup_dir(cli, BASEDIR)) {
631 mem_ctx = talloc_init("torture_raw_oplock");
633 if (!test_oplock(cli, mem_ctx)) {
637 smb_raw_exit(cli->session);
638 smbcli_deltree(cli->tree, BASEDIR);
639 torture_close_connection(cli);
640 talloc_free(mem_ctx);
646 stress testing of oplocks
648 BOOL torture_bench_oplock(struct torture_context *torture)
650 struct smbcli_state **cli;
652 TALLOC_CTX *mem_ctx = talloc_new(torture);
653 extern int torture_nprocs;
655 int timelimit = lp_parm_int(-1, "torture", "timelimit", 10);
658 struct event_context *ev = event_context_find(mem_ctx);
660 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
662 printf("Opening %d connections\n", torture_nprocs);
663 for (i=0;i<torture_nprocs;i++) {
664 if (!torture_open_connection_ev(&cli[i], ev)) {
667 talloc_steal(mem_ctx, cli[i]);
668 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
672 if (!torture_setup_dir(cli[0], BASEDIR)) {
677 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
678 io.ntcreatex.in.root_fid = 0;
679 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
680 io.ntcreatex.in.alloc_size = 0;
681 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
682 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
683 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
684 io.ntcreatex.in.create_options = 0;
685 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
686 io.ntcreatex.in.security_flags = 0;
687 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
688 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
689 NTCREATEX_FLAGS_REQUEST_OPLOCK |
690 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
692 tv = timeval_current();
695 we open the same file with SHARE_ACCESS_NONE from all the
696 connections in a round robin fashion. Each open causes an
697 oplock break on the previous connection, which is answered
698 by the oplock_handler_close() to close the file.
700 This measures how fast we can pass on oplocks, and stresses
701 the oplock handling code
703 printf("Running for %d seconds\n", timelimit);
704 while (timeval_elapsed(&tv) < timelimit) {
705 for (i=0;i<torture_nprocs;i++) {
708 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
709 CHECK_STATUS(status, NT_STATUS_OK);
712 printf("%.2f ops/second\r", count/timeval_elapsed(&tv));
715 printf("%.2f ops/second\n", count/timeval_elapsed(&tv));
717 smb_raw_exit(cli[torture_nprocs-1]->session);
720 smb_raw_exit(cli[0]->session);
721 smbcli_deltree(cli[0]->tree, BASEDIR);
722 talloc_free(mem_ctx);