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
57 static BOOL oplock_handler_ack(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
59 struct smbcli_tree *tree = private;
60 break_info.fnum = fnum;
61 break_info.level = level;
64 printf("Acking in oplock handler\n");
66 return smbcli_oplock_ack(tree, fnum, level);
69 static void oplock_handler_close_recv(struct smbcli_request *req)
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++;
80 a handler function for oplock break requests - close the file
82 static BOOL oplock_handler_close(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
85 struct smbcli_tree *tree = private;
86 struct smbcli_request *req;
88 break_info.fnum = fnum;
89 break_info.level = level;
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);
97 printf("failed to send close in oplock_handler_close\n");
101 req->async.fn = oplock_handler_close_recv;
102 req->async.private = NULL;
110 static BOOL test_oplock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
112 const char *fname = BASEDIR "\\test_oplock.dat";
116 union smb_unlink unl;
118 uint16_t fnum=0, fnum2=0;
121 smbcli_unlink(cli->tree, fname);
123 smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
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;
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;
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);
149 printf("a 2nd open should not cause a break\n");
150 status = smb_raw_open(cli->tree, mem_ctx, &io);
151 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
152 CHECK_VAL(break_info.count, 0);
153 CHECK_VAL(break_info.failures, 0);
155 printf("unlink it - should also be no break\n");
156 unl.unlink.in.pattern = fname;
157 unl.unlink.in.attrib = 0;
158 status = smb_raw_unlink(cli->tree, &unl);
159 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
160 CHECK_VAL(break_info.count, 0);
161 CHECK_VAL(break_info.failures, 0);
163 smbcli_close(cli->tree, fnum);
166 with a batch oplock we get a break
168 printf("open with batch oplock\n");
169 ZERO_STRUCT(break_info);
170 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
171 NTCREATEX_FLAGS_REQUEST_OPLOCK |
172 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
173 status = smb_raw_open(cli->tree, mem_ctx, &io);
174 CHECK_STATUS(status, NT_STATUS_OK);
175 fnum = io.ntcreatex.out.file.fnum;
176 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
178 printf("unlink should generate a break\n");
179 unl.unlink.in.pattern = fname;
180 unl.unlink.in.attrib = 0;
181 status = smb_raw_unlink(cli->tree, &unl);
182 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
184 CHECK_VAL(break_info.fnum, fnum);
185 CHECK_VAL(break_info.level, 1);
186 CHECK_VAL(break_info.count, 1);
187 CHECK_VAL(break_info.failures, 0);
189 smbcli_close(cli->tree, fnum);
191 printf("if we close on break then the unlink can succeed\n");
192 ZERO_STRUCT(break_info);
193 smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
194 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
195 NTCREATEX_FLAGS_REQUEST_OPLOCK |
196 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
197 status = smb_raw_open(cli->tree, mem_ctx, &io);
198 CHECK_STATUS(status, NT_STATUS_OK);
199 fnum = io.ntcreatex.out.file.fnum;
200 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
202 unl.unlink.in.pattern = fname;
203 unl.unlink.in.attrib = 0;
204 ZERO_STRUCT(break_info);
205 status = smb_raw_unlink(cli->tree, &unl);
206 CHECK_STATUS(status, NT_STATUS_OK);
208 CHECK_VAL(break_info.fnum, fnum);
209 CHECK_VAL(break_info.level, 1);
210 CHECK_VAL(break_info.count, 1);
211 CHECK_VAL(break_info.failures, 0);
213 printf("a self read should not cause a break\n");
214 ZERO_STRUCT(break_info);
215 smbcli_close(cli->tree, fnum);
216 smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
218 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
219 NTCREATEX_FLAGS_REQUEST_OPLOCK |
220 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
221 status = smb_raw_open(cli->tree, mem_ctx, &io);
222 CHECK_STATUS(status, NT_STATUS_OK);
223 fnum = io.ntcreatex.out.file.fnum;
224 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
226 rd.read.level = RAW_READ_READ;
227 rd.read.in.file.fnum = fnum;
228 rd.read.in.count = 1;
229 rd.read.in.offset = 0;
230 rd.read.in.remaining = 0;
231 status = smb_raw_read(cli->tree, &rd);
232 CHECK_STATUS(status, NT_STATUS_OK);
233 CHECK_VAL(break_info.count, 0);
234 CHECK_VAL(break_info.failures, 0);
236 printf("a 2nd open should give a break\n");
237 ZERO_STRUCT(break_info);
238 smbcli_close(cli->tree, fnum);
239 smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
241 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
242 NTCREATEX_FLAGS_REQUEST_OPLOCK |
243 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
244 status = smb_raw_open(cli->tree, mem_ctx, &io);
245 CHECK_STATUS(status, NT_STATUS_OK);
246 fnum = io.ntcreatex.out.file.fnum;
247 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
249 ZERO_STRUCT(break_info);
251 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
252 status = smb_raw_open(cli->tree, mem_ctx, &io);
253 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
255 CHECK_VAL(break_info.count, 1);
256 CHECK_VAL(break_info.fnum, fnum);
257 CHECK_VAL(break_info.level, 1);
258 CHECK_VAL(break_info.failures, 0);
260 printf("a 2nd open should get an oplock when we close instead of ack\n");
261 ZERO_STRUCT(break_info);
262 smbcli_close(cli->tree, fnum);
263 smbcli_oplock_handler(cli->transport, oplock_handler_close, cli->tree);
265 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
266 NTCREATEX_FLAGS_REQUEST_OPLOCK |
267 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
268 status = smb_raw_open(cli->tree, mem_ctx, &io);
269 CHECK_STATUS(status, NT_STATUS_OK);
270 fnum2 = io.ntcreatex.out.file.fnum;
271 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
273 ZERO_STRUCT(break_info);
275 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
276 NTCREATEX_FLAGS_REQUEST_OPLOCK |
277 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
278 status = smb_raw_open(cli->tree, mem_ctx, &io);
279 CHECK_STATUS(status, NT_STATUS_OK);
280 fnum = io.ntcreatex.out.file.fnum;
281 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
283 CHECK_VAL(break_info.count, 1);
284 CHECK_VAL(break_info.fnum, fnum2);
285 CHECK_VAL(break_info.level, 1);
286 CHECK_VAL(break_info.failures, 0);
288 smbcli_close(cli->tree, fnum);
290 printf("open with batch oplock\n");
291 ZERO_STRUCT(break_info);
292 smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
294 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
295 NTCREATEX_FLAGS_REQUEST_OPLOCK |
296 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
297 status = smb_raw_open(cli->tree, mem_ctx, &io);
298 CHECK_STATUS(status, NT_STATUS_OK);
299 fnum = io.ntcreatex.out.file.fnum;
300 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
302 ZERO_STRUCT(break_info);
303 printf("second open with attributes only shouldn't cause oplock break\n");
305 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
306 NTCREATEX_FLAGS_REQUEST_OPLOCK |
307 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
308 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
309 status = smb_raw_open(cli->tree, mem_ctx, &io);
310 CHECK_STATUS(status, NT_STATUS_OK);
311 fnum2 = io.ntcreatex.out.file.fnum;
312 CHECK_VAL(io.ntcreatex.out.oplock_level, NO_OPLOCK_RETURN);
313 CHECK_VAL(break_info.count, 0);
314 CHECK_VAL(break_info.fnum, 0);
315 CHECK_VAL(break_info.level, 0);
316 CHECK_VAL(break_info.failures, 0);
318 smbcli_close(cli->tree, fnum);
319 smbcli_close(cli->tree, fnum2);
320 smbcli_unlink(cli->tree, fname);
322 printf("open with attributes only can create file\n");
323 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
324 NTCREATEX_FLAGS_REQUEST_OPLOCK |
325 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
326 io.ntcreatex.in.access_mask = SEC_FILE_READ_ATTRIBUTE|SEC_FILE_WRITE_ATTRIBUTE|SEC_STD_SYNCHRONIZE;
327 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
328 status = smb_raw_open(cli->tree, mem_ctx, &io);
329 CHECK_STATUS(status, NT_STATUS_OK);
330 fnum = io.ntcreatex.out.file.fnum;
331 CHECK_VAL(io.ntcreatex.out.oplock_level, BATCH_OPLOCK_RETURN);
333 printf("Subsequent normal open should break oplock on attribute only open to level II\n");
335 ZERO_STRUCT(break_info);
336 smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
338 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
339 NTCREATEX_FLAGS_REQUEST_OPLOCK |
340 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
341 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
342 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
343 status = smb_raw_open(cli->tree, mem_ctx, &io);
344 CHECK_STATUS(status, NT_STATUS_OK);
345 fnum2 = io.ntcreatex.out.file.fnum;
346 CHECK_VAL(break_info.count, 1);
347 CHECK_VAL(break_info.fnum, fnum);
348 CHECK_VAL(break_info.failures, 0);
349 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
350 smbcli_close(cli->tree, fnum2);
352 printf("third oplocked open should grant level2 without break\n");
353 ZERO_STRUCT(break_info);
354 smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
355 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
356 NTCREATEX_FLAGS_REQUEST_OPLOCK |
357 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
358 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
359 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
360 status = smb_raw_open(cli->tree, mem_ctx, &io);
361 CHECK_STATUS(status, NT_STATUS_OK);
362 fnum2 = io.ntcreatex.out.file.fnum;
363 CHECK_VAL(break_info.count, 0);
364 CHECK_VAL(break_info.failures, 0);
365 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
367 ZERO_STRUCT(break_info);
369 printf("write should trigger a break to none on both\n");
372 wr.write.level = RAW_WRITE_WRITE;
373 wr.write.in.file.fnum = fnum2;
374 wr.write.in.count = 1;
375 wr.write.in.offset = 0;
376 wr.write.in.remaining = 0;
377 wr.write.in.data = (const uint8_t *)"x";
378 status = smb_raw_write(cli->tree, &wr);
379 CHECK_STATUS(status, NT_STATUS_OK);
382 /* Now the oplock break request comes in. But right now we can't
383 * answer it. Do another write */
389 wr.write.level = RAW_WRITE_WRITE;
390 wr.write.in.file.fnum = fnum2;
391 wr.write.in.count = 1;
392 wr.write.in.offset = 0;
393 wr.write.in.remaining = 0;
394 wr.write.in.data = (const uint8_t *)"x";
395 status = smb_raw_write(cli->tree, &wr);
396 CHECK_STATUS(status, NT_STATUS_OK);
399 CHECK_VAL(break_info.count, 2);
400 CHECK_VAL(break_info.level, 0);
401 CHECK_VAL(break_info.failures, 0);
403 smbcli_close(cli->tree, fnum);
404 smbcli_close(cli->tree, fnum2);
406 ZERO_STRUCT(break_info);
407 smbcli_oplock_handler(cli->transport, oplock_handler_ack, cli->tree);
409 printf("Open with oplock after a on-oplock open should grant level2\n");
410 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
411 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
412 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
413 NTCREATEX_SHARE_ACCESS_WRITE|
414 NTCREATEX_SHARE_ACCESS_DELETE;
415 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
416 status = smb_raw_open(cli->tree, mem_ctx, &io);
417 CHECK_STATUS(status, NT_STATUS_OK);
418 fnum = io.ntcreatex.out.file.fnum;
419 CHECK_VAL(break_info.count, 0);
420 CHECK_VAL(break_info.fnum, 0);
421 CHECK_VAL(break_info.failures, 0);
422 CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
424 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
425 NTCREATEX_FLAGS_REQUEST_OPLOCK |
426 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
427 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
428 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
429 NTCREATEX_SHARE_ACCESS_WRITE|
430 NTCREATEX_SHARE_ACCESS_DELETE;
431 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
432 status = smb_raw_open(cli->tree, mem_ctx, &io);
433 CHECK_STATUS(status, NT_STATUS_OK);
434 fnum2 = io.ntcreatex.out.file.fnum;
435 CHECK_VAL(break_info.count, 0);
436 CHECK_VAL(break_info.fnum, 0);
437 CHECK_VAL(break_info.failures, 0);
438 CHECK_VAL(io.ntcreatex.out.oplock_level, LEVEL_II_OPLOCK_RETURN);
440 printf("write should trigger a break to none\n");
443 wr.write.level = RAW_WRITE_WRITE;
444 wr.write.in.file.fnum = fnum;
445 wr.write.in.count = 1;
446 wr.write.in.offset = 0;
447 wr.write.in.remaining = 0;
448 wr.write.in.data = (const uint8_t *)"x";
449 status = smb_raw_write(cli->tree, &wr);
450 CHECK_STATUS(status, NT_STATUS_OK);
453 /* Now the oplock break request comes in. But right now we can't
454 * answer it. Do another write */
460 wr.write.level = RAW_WRITE_WRITE;
461 wr.write.in.file.fnum = fnum;
462 wr.write.in.count = 1;
463 wr.write.in.offset = 0;
464 wr.write.in.remaining = 0;
465 wr.write.in.data = (const uint8_t *)"x";
466 status = smb_raw_write(cli->tree, &wr);
467 CHECK_STATUS(status, NT_STATUS_OK);
470 CHECK_VAL(break_info.count, 1);
471 CHECK_VAL(break_info.fnum, fnum2);
472 CHECK_VAL(break_info.level, 0);
473 CHECK_VAL(break_info.failures, 0);
476 smbcli_close(cli->tree, fnum);
477 smbcli_close(cli->tree, fnum2);
478 smbcli_unlink(cli->tree, fname);
484 basic testing of oplocks
486 BOOL torture_raw_oplock(struct torture_context *torture)
488 struct smbcli_state *cli;
492 if (!torture_open_connection(&cli)) {
496 if (!torture_setup_dir(cli, BASEDIR)) {
500 mem_ctx = talloc_init("torture_raw_oplock");
502 if (!test_oplock(cli, mem_ctx)) {
506 smb_raw_exit(cli->session);
507 smbcli_deltree(cli->tree, BASEDIR);
508 torture_close_connection(cli);
509 talloc_free(mem_ctx);
515 stress testing of oplocks
517 BOOL torture_bench_oplock(struct torture_context *torture)
519 struct smbcli_state **cli;
521 TALLOC_CTX *mem_ctx = talloc_new(torture);
522 extern int torture_nprocs;
524 int timelimit = lp_parm_int(-1, "torture", "timelimit", 10);
527 struct event_context *ev = event_context_find(mem_ctx);
529 cli = talloc_array(mem_ctx, struct smbcli_state *, torture_nprocs);
531 printf("Opening %d connections\n", torture_nprocs);
532 for (i=0;i<torture_nprocs;i++) {
533 if (!torture_open_connection_ev(&cli[i], ev)) {
536 talloc_steal(mem_ctx, cli[i]);
537 smbcli_oplock_handler(cli[i]->transport, oplock_handler_close,
541 if (!torture_setup_dir(cli[0], BASEDIR)) {
546 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
547 io.ntcreatex.in.root_fid = 0;
548 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
549 io.ntcreatex.in.alloc_size = 0;
550 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
551 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
552 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
553 io.ntcreatex.in.create_options = 0;
554 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
555 io.ntcreatex.in.security_flags = 0;
556 io.ntcreatex.in.fname = BASEDIR "\\test.dat";
557 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
558 NTCREATEX_FLAGS_REQUEST_OPLOCK |
559 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
561 tv = timeval_current();
564 we open the same file with SHARE_ACCESS_NONE from all the
565 connections in a round robin fashion. Each open causes an
566 oplock break on the previous connection, which is answered
567 by the oplock_handler_close() to close the file.
569 This measures how fast we can pass on oplocks, and stresses
570 the oplock handling code
572 printf("Running for %d seconds\n", timelimit);
573 while (timeval_elapsed(&tv) < timelimit) {
574 for (i=0;i<torture_nprocs;i++) {
577 status = smb_raw_open(cli[i]->tree, mem_ctx, &io);
578 CHECK_STATUS(status, NT_STATUS_OK);
581 printf("%.2f ops/second\r", count/timeval_elapsed(&tv));
584 printf("%.2f ops/second\n", count/timeval_elapsed(&tv));
586 smb_raw_exit(cli[torture_nprocs-1]->session);
589 smb_raw_exit(cli[0]->session);
590 smbcli_deltree(cli[0]->tree, BASEDIR);
591 talloc_free(mem_ctx);