r15014: added a simple batch oplock benchmark
[samba.git] / source4 / torture / raw / oplock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    basic raw test suite for oplocks
4    Copyright (C) Andrew Tridgell 2003
5    
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.
10    
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.
15    
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.
19 */
20
21 #include "includes.h"
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"
28
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); \
33                 ret = False; \
34         }} while (0)
35
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)); \
40                 ret = False; \
41                 goto done; \
42         }} while (0)
43
44
45 static struct {
46         int fnum;
47         uint8_t level;
48         int count;
49         int failures;
50 } break_info;
51
52 #define BASEDIR "\\test_notify"
53
54 /*
55   a handler function for oplock break requests
56 */
57 static BOOL oplock_handler_ack(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
58 {
59         struct smbcli_tree *tree = private;
60         break_info.fnum = fnum;
61         break_info.level = level;
62         break_info.count++;
63
64         printf("Acking in oplock handler\n");
65
66         return smbcli_oplock_ack(tree, fnum, level);
67 }
68
69 static void oplock_handler_close_recv(struct smbcli_request *req)
70 {
71         NTSTATUS status;
72         status = smbcli_request_simple_recv(req);
73         if (!NT_STATUS_IS_OK(status)) {
74                 printf("close failed in oplock_handler_close\n");
75                 break_info.failures++;
76         }
77 }
78
79 /*
80   a handler function for oplock break requests - close the file
81 */
82 static BOOL oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
83 {
84         union smb_close io;
85         struct smbcli_tree *tree = private;
86         struct smbcli_request *req;
87
88         break_info.fnum = fnum;
89         break_info.level = level;
90         break_info.count++;
91
92         io.close.level = RAW_CLOSE_CLOSE;
93         io.close.in.file.fnum = fnum;
94         io.close.in.write_time = 0;
95         req = smb_raw_close_send(tree, &io);
96         if (req == NULL) {
97                 printf("failed to send close in oplock_handler_close\n");
98                 return False;
99         }
100
101         req->async.fn = oplock_handler_close_recv;
102         req->async.private = NULL;
103
104         return True;
105 }
106
107 /*
108   test oplock ops
109 */
110 static BOOL test_oplock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
111 {
112         const char *fname = BASEDIR "\\test_oplock.dat";
113         NTSTATUS status;
114         BOOL ret = True;
115         union smb_open io;
116         union smb_unlink unl;
117         union smb_read rd;
118         uint16_t fnum=0, fnum2=0;
119
120         /* cleanup */
121         smbcli_unlink(cli->tree, fname);
122
123         smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
124
125         /*
126           base ntcreatex parms
127         */
128         io.generic.level = RAW_OPEN_NTCREATEX;
129         io.ntcreatex.in.root_fid = 0;
130         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
131         io.ntcreatex.in.alloc_size = 0;
132         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
133         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
134         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
135         io.ntcreatex.in.create_options = 0;
136         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
137         io.ntcreatex.in.security_flags = 0;
138         io.ntcreatex.in.fname = fname;
139
140         printf("open a file with a normal oplock\n");
141         ZERO_STRUCT(break_info);
142         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK;
143
144         status = smb_raw_open(cli->tree, mem_ctx, &io);
145         CHECK_STATUS(status, NT_STATUS_OK);
146         fnum = io.ntcreatex.out.file.fnum;
147         CHECK_VAL(io.ntcreatex.out.oplock_level, EXCLUSIVE_OPLOCK_RETURN);
148
149         printf("unlink it - should be no break\n");
150         unl.unlink.in.pattern = fname;
151         unl.unlink.in.attrib = 0;
152         status = smb_raw_unlink(cli->tree, &unl);
153         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
154         CHECK_VAL(break_info.count, 0);
155         CHECK_VAL(break_info.failures, 0);
156
157         smbcli_close(cli->tree, fnum);
158
159         /*
160           with a batch oplock we get a break
161         */
162         printf("open with batch oplock\n");
163         ZERO_STRUCT(break_info);
164         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
165                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
166                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
167         status = smb_raw_open(cli->tree, mem_ctx, &io);
168         CHECK_STATUS(status, NT_STATUS_OK);
169         fnum = io.ntcreatex.out.file.fnum;
170         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
171
172         printf("unlink should generate a break\n");
173         unl.unlink.in.pattern = fname;
174         unl.unlink.in.attrib = 0;
175         status = smb_raw_unlink(cli->tree, &unl);
176         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
177
178         CHECK_VAL(break_info.fnum, fnum);
179         CHECK_VAL(break_info.level, 1);
180         CHECK_VAL(break_info.count, 1);
181         CHECK_VAL(break_info.failures, 0);
182
183         smbcli_close(cli->tree, fnum);
184
185         printf("if we close on break then the unlink can succeed\n");
186         ZERO_STRUCT(break_info);
187         smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
188         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
189                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
190                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
191         status = smb_raw_open(cli->tree, mem_ctx, &io);
192         CHECK_STATUS(status, NT_STATUS_OK);
193         fnum = io.ntcreatex.out.file.fnum;
194         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
195
196         unl.unlink.in.pattern = fname;
197         unl.unlink.in.attrib = 0;
198         ZERO_STRUCT(break_info);
199         status = smb_raw_unlink(cli->tree, &unl);
200         CHECK_STATUS(status, NT_STATUS_OK);
201
202         CHECK_VAL(break_info.fnum, fnum);
203         CHECK_VAL(break_info.level, 1);
204         CHECK_VAL(break_info.count, 1);
205         CHECK_VAL(break_info.failures, 0);
206
207         printf("a self read should not cause a break\n");
208         ZERO_STRUCT(break_info);
209         smbcli_close(cli->tree, fnum);
210         smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
211
212         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
213                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
214                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
215         status = smb_raw_open(cli->tree, mem_ctx, &io);
216         CHECK_STATUS(status, NT_STATUS_OK);
217         fnum = io.ntcreatex.out.file.fnum;
218         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
219
220         rd.read.level = RAW_READ_READ;
221         rd.read.in.file.fnum = fnum;
222         rd.read.in.count = 1;
223         rd.read.in.offset = 0;
224         rd.read.in.remaining = 0;
225         status = smb_raw_read(cli->tree, &rd);
226         CHECK_STATUS(status, NT_STATUS_OK);
227         CHECK_VAL(break_info.count, 0);
228         CHECK_VAL(break_info.failures, 0);
229
230         printf("a 2nd open should give a break\n");
231         ZERO_STRUCT(break_info);
232         smbcli_close(cli->tree, fnum);
233         smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
234
235         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
236                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
237                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
238         status = smb_raw_open(cli->tree, mem_ctx, &io);
239         CHECK_STATUS(status, NT_STATUS_OK);
240         fnum = io.ntcreatex.out.file.fnum;
241         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
242
243         ZERO_STRUCT(break_info);
244
245         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
246         status = smb_raw_open(cli->tree, mem_ctx, &io);
247         CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
248
249         CHECK_VAL(break_info.count, 1);
250         CHECK_VAL(break_info.fnum, fnum);
251         CHECK_VAL(break_info.level, 1);
252         CHECK_VAL(break_info.failures, 0);
253
254         printf("a 2nd open should get an oplock when we close instead of ack\n");
255         ZERO_STRUCT(break_info);
256         smbcli_close(cli->tree, fnum);
257         smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
258
259         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
260                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
261                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
262         status = smb_raw_open(cli->tree, mem_ctx, &io);
263         CHECK_STATUS(status, NT_STATUS_OK);
264         fnum2 = io.ntcreatex.out.file.fnum;
265         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
266
267         ZERO_STRUCT(break_info);
268
269         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
270                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
271                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
272         status = smb_raw_open(cli->tree, mem_ctx, &io);
273         CHECK_STATUS(status, NT_STATUS_OK);
274         fnum = io.ntcreatex.out.file.fnum;
275         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
276
277         CHECK_VAL(break_info.count, 1);
278         CHECK_VAL(break_info.fnum, fnum2);
279         CHECK_VAL(break_info.level, 1);
280         CHECK_VAL(break_info.failures, 0);
281         
282         smbcli_close(cli->tree, fnum);
283
284         printf("open with batch oplock\n");
285         ZERO_STRUCT(break_info);
286         smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
287
288         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
289                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
290                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
291         status = smb_raw_open(cli->tree, mem_ctx, &io);
292         CHECK_STATUS(status, NT_STATUS_OK);
293         fnum = io.ntcreatex.out.file.fnum;
294         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
295
296         ZERO_STRUCT(break_info);
297         printf("second open with attributes only shouldn't cause oplock break\n");
298
299         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
300                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
301                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
302         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
303         status = smb_raw_open(cli->tree, mem_ctx, &io);
304         CHECK_STATUS(status, NT_STATUS_OK);
305         fnum2 = io.ntcreatex.out.file.fnum;
306         CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
307         CHECK_VAL(break_info.count, 0);
308         CHECK_VAL(break_info.fnum, 0);
309         CHECK_VAL(break_info.level, 0);
310         CHECK_VAL(break_info.failures, 0);
311
312         smbcli_close(cli->tree, fnum);
313         smbcli_close(cli->tree, fnum2);
314         smbcli_unlink(cli->tree, fname);
315
316         printf("open with attributes only can create file\n");
317         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
318                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
319                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
320         io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
321         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
322         status = smb_raw_open(cli->tree, mem_ctx, &io);
323         CHECK_STATUS(status, NT_STATUS_OK);
324         fnum = io.ntcreatex.out.file.fnum;
325         CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
326
327         printf("Subsequent normal open should break oplock on attribute only open to level II\n");
328
329         ZERO_STRUCT(break_info);
330         smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
331
332         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
333                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
334                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
335         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
336         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
337         status = smb_raw_open(cli->tree, mem_ctx, &io);
338         CHECK_STATUS(status, NT_STATUS_OK);
339         fnum2 = io.ntcreatex.out.file.fnum;
340         CHECK_VAL(break_info.count, 1);
341         CHECK_VAL(break_info.fnum, fnum);
342         CHECK_VAL(break_info.failures, 0);
343         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
344         smbcli_close(cli->tree, fnum2);
345
346         printf("third oplocked open should grant level2 without break\n");
347         ZERO_STRUCT(break_info);
348         smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
349         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
350                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
351                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
352         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
353         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
354         status = smb_raw_open(cli->tree, mem_ctx, &io);
355         CHECK_STATUS(status, NT_STATUS_OK);
356         fnum2 = io.ntcreatex.out.file.fnum;
357         CHECK_VAL(break_info.count, 0);
358         CHECK_VAL(break_info.failures, 0);
359         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
360
361         ZERO_STRUCT(break_info);
362
363         printf("write should trigger a break to none on both\n");
364         {
365                 union smb_write wr;
366                 wr.write.level = RAW_WRITE_WRITE;
367                 wr.write.in.file.fnum = fnum2;
368                 wr.write.in.count = 1;
369                 wr.write.in.offset = 0;
370                 wr.write.in.remaining = 0;
371                 wr.write.in.data = (const uint8_t *)"x";
372                 status = smb_raw_write(cli->tree, &wr);
373                 CHECK_STATUS(status, NT_STATUS_OK);
374         }
375
376         /* Now the oplock break request comes in. But right now we can't
377          * answer it. Do another write */
378
379         msleep(100);
380         
381         {
382                 union smb_write wr;
383                 wr.write.level = RAW_WRITE_WRITE;
384                 wr.write.in.file.fnum = fnum2;
385                 wr.write.in.count = 1;
386                 wr.write.in.offset = 0;
387                 wr.write.in.remaining = 0;
388                 wr.write.in.data = (const uint8_t *)"x";
389                 status = smb_raw_write(cli->tree, &wr);
390                 CHECK_STATUS(status, NT_STATUS_OK);
391         }
392
393         CHECK_VAL(break_info.count, 2);
394         CHECK_VAL(break_info.level, 0);
395         CHECK_VAL(break_info.failures, 0);
396
397         smbcli_close(cli->tree, fnum);
398         smbcli_close(cli->tree, fnum2);
399
400         ZERO_STRUCT(break_info);
401         smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
402
403         printf("Open with oplock after a on-oplock open should grant level2\n");
404         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
405         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
406         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
407                 NTCREATEX_SHARE_ACCESS_WRITE|
408                 NTCREATEX_SHARE_ACCESS_DELETE;
409         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
410         status = smb_raw_open(cli->tree, mem_ctx, &io);
411         CHECK_STATUS(status, NT_STATUS_OK);
412         fnum = io.ntcreatex.out.file.fnum;
413         CHECK_VAL(break_info.count, 0);
414         CHECK_VAL(break_info.fnum, 0);
415         CHECK_VAL(break_info.failures, 0);
416         CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
417
418         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
419                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
420                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
421         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
422         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
423                 NTCREATEX_SHARE_ACCESS_WRITE|
424                 NTCREATEX_SHARE_ACCESS_DELETE;
425         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
426         status = smb_raw_open(cli->tree, mem_ctx, &io);
427         CHECK_STATUS(status, NT_STATUS_OK);
428         fnum2 = io.ntcreatex.out.file.fnum;
429         CHECK_VAL(break_info.count, 0);
430         CHECK_VAL(break_info.fnum, 0);
431         CHECK_VAL(break_info.failures, 0);
432         CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
433
434         printf("write should trigger a break to none\n");
435         {
436                 union smb_write wr;
437                 wr.write.level = RAW_WRITE_WRITE;
438                 wr.write.in.file.fnum = fnum;
439                 wr.write.in.count = 1;
440                 wr.write.in.offset = 0;
441                 wr.write.in.remaining = 0;
442                 wr.write.in.data = (const uint8_t *)"x";
443                 status = smb_raw_write(cli->tree, &wr);
444                 CHECK_STATUS(status, NT_STATUS_OK);
445         }
446
447         /* Now the oplock break request comes in. But right now we can't
448          * answer it. Do another write */
449
450         msleep(100);
451         
452         {
453                 union smb_write wr;
454                 wr.write.level = RAW_WRITE_WRITE;
455                 wr.write.in.file.fnum = fnum;
456                 wr.write.in.count = 1;
457                 wr.write.in.offset = 0;
458                 wr.write.in.remaining = 0;
459                 wr.write.in.data = (const uint8_t *)"x";
460                 status = smb_raw_write(cli->tree, &wr);
461                 CHECK_STATUS(status, NT_STATUS_OK);
462         }
463
464         CHECK_VAL(break_info.count, 1);
465         CHECK_VAL(break_info.fnum, fnum2);
466         CHECK_VAL(break_info.level, 0);
467         CHECK_VAL(break_info.failures, 0);
468
469 done:
470         smbcli_close(cli->tree, fnum);
471         smbcli_close(cli->tree, fnum2);
472         smbcli_unlink(cli->tree, fname);
473         return ret;
474 }
475
476
477 /* 
478    basic testing of oplocks
479 */
480 BOOL torture_raw_oplock(struct torture_context *torture)
481 {
482         struct smbcli_state *cli;
483         BOOL ret = True;
484         TALLOC_CTX *mem_ctx;
485
486         if (!torture_open_connection(&cli)) {
487                 return False;
488         }
489
490         if (!torture_setup_dir(cli, BASEDIR)) {
491                 return False;
492         }
493
494         mem_ctx = talloc_init("torture_raw_oplock");
495
496         if (!test_oplock(cli, mem_ctx)) {
497                 ret = False;
498         }
499
500         smb_raw_exit(cli->session);
501         smbcli_deltree(cli->tree, BASEDIR);
502         torture_close_connection(cli);
503         talloc_free(mem_ctx);
504         return ret;
505 }
506
507
508 /* 
509    stress testing of oplocks
510 */
511 BOOL torture_bench_oplock(struct torture_context *torture)
512 {
513         struct smbcli_state **cli;
514         BOOL ret = True;
515         TALLOC_CTX *mem_ctx = talloc_new(torture);
516         extern int torture_nprocs;
517         int i, count=0;
518         int timelimit = lp_parm_int(-1, "torture", "timelimit", 10);
519         union smb_open io;
520         struct timeval tv;
521         struct event_context *ev = event_context_find(mem_ctx);
522
523         cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
524
525         printf("Opening %d connections\n", torture_nprocs);
526         for (i=0;i<torture_nprocs;i++) {
527                 if (!torture_open_connection_ev(&cli[i], ev)) {
528                         return False;
529                 }
530                 talloc_steal(mem_ctx, cli[i]);
531                 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close, 
532                                       cli[i]->tree);
533         }
534
535         if (!torture_setup_dir(cli[0], BASEDIR)) {
536                 ret = False;
537                 goto done;
538         }
539
540         io.ntcreatex.level = RAW_OPEN_NTCREATEX;
541         io.ntcreatex.in.root_fid = 0;
542         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
543         io.ntcreatex.in.alloc_size = 0;
544         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
545         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
546         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
547         io.ntcreatex.in.create_options = 0;
548         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
549         io.ntcreatex.in.security_flags = 0;
550         io.ntcreatex.in.fname = BASEDIR "\\test.dat";
551         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED | 
552                 NTCREATEX_FLAGS_REQUEST_OPLOCK | 
553                 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
554
555         tv = timeval_current(); 
556                 
557         printf("Running for %d seconds\n", timelimit);
558         while (timeval_elapsed(&tv) < timelimit) {
559                 for (i=0;i<torture_nprocs;i++) {
560                         NTSTATUS status;
561
562                         status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
563                         CHECK_STATUS(status, NT_STATUS_OK);
564                         count++;
565                 }
566                 printf("%.2f ops/second\r", count/timeval_elapsed(&tv));
567         }
568
569         printf("%.2f ops/second\n", count/timeval_elapsed(&tv));
570
571         smb_raw_exit(cli[torture_nprocs-1]->session);
572         
573 done:
574         smb_raw_exit(cli[0]->session);
575         smbcli_deltree(cli[0]->tree, BASEDIR);
576         talloc_free(mem_ctx);
577         return ret;
578 }