4 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 1997-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int nbench_line_count
;
30 static BOOL bypass_io
;
34 struct ftable
*next
, *prev
;
35 int fd
; /* the fd that we got back from the server */
36 int handle
; /* the handle in the load file */
39 static struct ftable
*ftable
;
42 double bytes_in
, bytes_out
;
47 double nbio_total(void)
51 for (i
=0;i
<nprocs
;i
++) {
52 total
+= children
[i
].bytes_out
+ children
[i
].bytes_in
;
57 void nb_warmup_done(void)
59 children
[nbio_id
].bytes_out
= 0;
60 children
[nbio_id
].bytes_in
= 0;
67 int lines
=0, num_clients
=0;
70 if (nbio_id
!= -1) return;
72 for (i
=0;i
<nprocs
;i
++) {
73 lines
+= children
[i
].line
;
74 if (!children
[i
].done
) num_clients
++;
80 printf("%4d %8d %.2f MB/sec warmup %.0f sec \n",
81 num_clients
, lines
/nprocs
,
82 1.0e-6 * nbio_total() / t
,
85 printf("%4d %8d %.2f MB/sec execute %.0f sec \n",
86 num_clients
, lines
/nprocs
,
87 1.0e-6 * nbio_total() / t
,
91 if (warmup
&& t
>= warmup
) {
98 signal(SIGALRM
, nb_alarm
);
102 void nbio_shmem(int n
)
105 children
= shm_setup(sizeof(*children
) * nprocs
);
107 printf("Failed to setup shared memory!\n");
112 static struct ftable
*find_ftable(int handle
)
116 for (f
=ftable
;f
;f
=f
->next
) {
117 if (f
->handle
== handle
) return f
;
122 static int find_handle(int handle
)
126 children
[nbio_id
].line
= nbench_line_count
;
128 f
= find_ftable(handle
);
132 printf("(%d) ERROR: handle %d was not found\n",
133 nbench_line_count
, handle
);
136 return -1; /* Not reached */
141 static struct smbcli_state
*c
;
144 a handler function for oplock break requests
146 static BOOL
oplock_handler(struct smbcli_transport
*transport
, uint16_t tid
, uint16_t fnum
, uint8_t level
, void *private)
148 struct smbcli_tree
*tree
= private;
149 return smbcli_oplock_ack(tree
, fnum
, level
);
152 void nb_setup(struct smbcli_state
*cli
, int id
, int warmupt
)
159 children
[nbio_id
].done
= 0;
162 printf("skipping I/O\n");
165 smbcli_oplock_handler(cli
->transport
, oplock_handler
, cli
->tree
);
170 static void check_status(const char *op
, NTSTATUS status
, NTSTATUS ret
)
172 if (!NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(ret
)) {
173 printf("[%d] Error: %s should have failed with %s\n",
174 nbench_line_count
, op
, nt_errstr(status
));
178 if (NT_STATUS_IS_OK(status
) && !NT_STATUS_IS_OK(ret
)) {
179 printf("[%d] Error: %s should have succeeded - %s\n",
180 nbench_line_count
, op
, nt_errstr(ret
));
184 if (!NT_STATUS_EQUAL(status
, ret
)) {
185 printf("[%d] Warning: got status %s but expected %s\n",
186 nbench_line_count
, nt_errstr(ret
), nt_errstr(status
));
191 void nb_unlink(const char *fname
, int attr
, NTSTATUS status
)
193 struct smb_unlink io
;
196 io
.in
.pattern
= fname
;
198 io
.in
.attrib
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
199 if (strchr(fname
, '*') == 0) {
200 io
.in
.attrib
|= FILE_ATTRIBUTE_DIRECTORY
;
203 ret
= smb_raw_unlink(c
->tree
, &io
);
205 check_status("Unlink", status
, ret
);
209 void nb_createx(const char *fname
,
210 uint_t create_options
, uint_t create_disposition
, int handle
,
214 uint32_t desired_access
;
220 mem_ctx
= talloc_init("raw_open");
222 if (create_options
& NTCREATEX_OPTIONS_DIRECTORY
) {
223 desired_access
= SA_RIGHT_FILE_READ_DATA
;
226 SA_RIGHT_FILE_READ_DATA
|
227 SA_RIGHT_FILE_WRITE_DATA
|
228 SA_RIGHT_FILE_READ_ATTRIBUTES
|
229 SA_RIGHT_FILE_WRITE_ATTRIBUTES
;
230 flags
= NTCREATEX_FLAGS_EXTENDED
|
231 NTCREATEX_FLAGS_REQUEST_OPLOCK
|
232 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
235 io
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
236 io
.ntcreatex
.in
.flags
= flags
;
237 io
.ntcreatex
.in
.root_fid
= 0;
238 io
.ntcreatex
.in
.access_mask
= desired_access
;
239 io
.ntcreatex
.in
.file_attr
= 0;
240 io
.ntcreatex
.in
.alloc_size
= 0;
241 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|NTCREATEX_SHARE_ACCESS_WRITE
;
242 io
.ntcreatex
.in
.open_disposition
= create_disposition
;
243 io
.ntcreatex
.in
.create_options
= create_options
;
244 io
.ntcreatex
.in
.impersonation
= 0;
245 io
.ntcreatex
.in
.security_flags
= 0;
246 io
.ntcreatex
.in
.fname
= fname
;
248 ret
= smb_raw_open(c
->tree
, mem_ctx
, &io
);
250 talloc_destroy(mem_ctx
);
252 check_status("NTCreateX", status
, ret
);
254 if (!NT_STATUS_IS_OK(ret
)) return;
256 f
= malloc(sizeof(struct ftable
));
258 f
->fd
= io
.ntcreatex
.out
.fnum
;
260 DLIST_ADD_END(ftable
, f
, struct ftable
*);
263 void nb_writex(int handle
, int offset
, int size
, int ret_size
, NTSTATUS status
)
270 i
= find_handle(handle
);
272 if (bypass_io
) return;
275 memset(buf
, 0xab, size
);
277 io
.writex
.level
= RAW_WRITE_WRITEX
;
278 io
.writex
.in
.fnum
= i
;
279 io
.writex
.in
.wmode
= 0;
280 io
.writex
.in
.remaining
= 0;
281 io
.writex
.in
.offset
= offset
;
282 io
.writex
.in
.count
= size
;
283 io
.writex
.in
.data
= buf
;
285 ret
= smb_raw_write(c
->tree
, &io
);
289 check_status("WriteX", status
, ret
);
291 if (NT_STATUS_IS_OK(ret
) && io
.writex
.out
.nwritten
!= ret_size
) {
292 printf("[%d] Warning: WriteX got count %d expected %d\n",
294 io
.writex
.out
.nwritten
, ret_size
);
297 children
[nbio_id
].bytes_out
+= ret_size
;
300 void nb_write(int handle
, int offset
, int size
, int ret_size
, NTSTATUS status
)
307 i
= find_handle(handle
);
309 if (bypass_io
) return;
313 memset(buf
, 0x12, size
);
315 io
.write
.level
= RAW_WRITE_WRITE
;
316 io
.write
.in
.fnum
= i
;
317 io
.write
.in
.remaining
= 0;
318 io
.write
.in
.offset
= offset
;
319 io
.write
.in
.count
= size
;
320 io
.write
.in
.data
= buf
;
322 ret
= smb_raw_write(c
->tree
, &io
);
326 check_status("Write", status
, ret
);
328 if (NT_STATUS_IS_OK(ret
) && io
.write
.out
.nwritten
!= ret_size
) {
329 printf("[%d] Warning: Write got count %d expected %d\n",
331 io
.write
.out
.nwritten
, ret_size
);
334 children
[nbio_id
].bytes_out
+= ret_size
;
338 void nb_lockx(int handle
, uint_t offset
, int size
, NTSTATUS status
)
343 struct smb_lock_entry lck
;
345 i
= find_handle(handle
);
351 io
.lockx
.level
= RAW_LOCK_LOCKX
;
352 io
.lockx
.in
.fnum
= i
;
353 io
.lockx
.in
.mode
= 0;
354 io
.lockx
.in
.timeout
= 0;
355 io
.lockx
.in
.ulock_cnt
= 0;
356 io
.lockx
.in
.lock_cnt
= 1;
357 io
.lockx
.in
.locks
= &lck
;
359 ret
= smb_raw_lock(c
->tree
, &io
);
361 check_status("LockX", status
, ret
);
364 void nb_unlockx(int handle
, uint_t offset
, int size
, NTSTATUS status
)
369 struct smb_lock_entry lck
;
371 i
= find_handle(handle
);
377 io
.lockx
.level
= RAW_LOCK_LOCKX
;
378 io
.lockx
.in
.fnum
= i
;
379 io
.lockx
.in
.mode
= 0;
380 io
.lockx
.in
.timeout
= 0;
381 io
.lockx
.in
.ulock_cnt
= 1;
382 io
.lockx
.in
.lock_cnt
= 0;
383 io
.lockx
.in
.locks
= &lck
;
385 ret
= smb_raw_lock(c
->tree
, &io
);
387 check_status("UnlockX", status
, ret
);
390 void nb_readx(int handle
, int offset
, int size
, int ret_size
, NTSTATUS status
)
397 i
= find_handle(handle
);
399 if (bypass_io
) return;
403 io
.readx
.level
= RAW_READ_READX
;
404 io
.readx
.in
.fnum
= i
;
405 io
.readx
.in
.offset
= offset
;
406 io
.readx
.in
.mincnt
= size
;
407 io
.readx
.in
.maxcnt
= size
;
408 io
.readx
.in
.remaining
= 0;
409 io
.readx
.out
.data
= buf
;
411 ret
= smb_raw_read(c
->tree
, &io
);
415 check_status("ReadX", status
, ret
);
417 if (NT_STATUS_IS_OK(ret
) && io
.readx
.out
.nread
!= ret_size
) {
418 printf("[%d] ERROR: ReadX got count %d expected %d\n",
420 io
.readx
.out
.nread
, ret_size
);
424 children
[nbio_id
].bytes_in
+= ret_size
;
427 void nb_close(int handle
, NTSTATUS status
)
433 i
= find_handle(handle
);
435 io
.close
.level
= RAW_CLOSE_CLOSE
;
436 io
.close
.in
.fnum
= i
;
437 io
.close
.in
.write_time
= 0;
439 ret
= smb_raw_close(c
->tree
, &io
);
441 check_status("Close", status
, ret
);
443 if (NT_STATUS_IS_OK(ret
)) {
444 struct ftable
*f
= find_ftable(handle
);
445 DLIST_REMOVE(ftable
, f
);
450 void nb_rmdir(const char *dname
, NTSTATUS status
)
457 ret
= smb_raw_rmdir(c
->tree
, &io
);
459 check_status("Rmdir", status
, ret
);
462 void nb_mkdir(const char *dname
, NTSTATUS status
)
466 io
.mkdir
.level
= RAW_MKDIR_MKDIR
;
467 io
.mkdir
.in
.path
= dname
;
469 /* NOTE! no error checking. Used for base fileset creation */
470 smb_raw_mkdir(c
->tree
, &io
);
473 void nb_rename(const char *old
, const char *new, NTSTATUS status
)
478 io
.generic
.level
= RAW_RENAME_RENAME
;
479 io
.rename
.in
.attrib
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
480 io
.rename
.in
.pattern1
= old
;
481 io
.rename
.in
.pattern2
= new;
483 ret
= smb_raw_rename(c
->tree
, &io
);
485 check_status("Rename", status
, ret
);
489 void nb_qpathinfo(const char *fname
, int level
, NTSTATUS status
)
491 union smb_fileinfo io
;
495 mem_ctx
= talloc_init("nb_qpathinfo");
497 io
.generic
.level
= level
;
498 io
.generic
.in
.fname
= fname
;
500 ret
= smb_raw_pathinfo(c
->tree
, mem_ctx
, &io
);
502 talloc_destroy(mem_ctx
);
504 check_status("Pathinfo", status
, ret
);
508 void nb_qfileinfo(int fnum
, int level
, NTSTATUS status
)
510 union smb_fileinfo io
;
515 i
= find_handle(fnum
);
517 mem_ctx
= talloc_init("nb_qfileinfo");
519 io
.generic
.level
= level
;
520 io
.generic
.in
.fnum
= i
;
522 ret
= smb_raw_fileinfo(c
->tree
, mem_ctx
, &io
);
524 talloc_destroy(mem_ctx
);
526 check_status("Fileinfo", status
, ret
);
529 void nb_sfileinfo(int fnum
, int level
, NTSTATUS status
)
531 union smb_setfileinfo io
;
535 if (level
!= RAW_SFILEINFO_BASIC_INFORMATION
) {
536 printf("[%d] Warning: setfileinfo level %d not handled\n", nbench_line_count
, level
);
542 i
= find_handle(fnum
);
544 io
.generic
.level
= level
;
545 io
.generic
.file
.fnum
= i
;
546 unix_to_nt_time(&io
.basic_info
.in
.create_time
, time(NULL
));
547 unix_to_nt_time(&io
.basic_info
.in
.access_time
, 0);
548 unix_to_nt_time(&io
.basic_info
.in
.write_time
, 0);
549 unix_to_nt_time(&io
.basic_info
.in
.change_time
, 0);
550 io
.basic_info
.in
.attrib
= 0;
552 ret
= smb_raw_setfileinfo(c
->tree
, &io
);
554 check_status("Setfileinfo", status
, ret
);
557 void nb_qfsinfo(int level
, NTSTATUS status
)
563 mem_ctx
= talloc_init("smbcli_dskattr");
565 io
.generic
.level
= level
;
566 ret
= smb_raw_fsinfo(c
->tree
, mem_ctx
, &io
);
568 talloc_destroy(mem_ctx
);
570 check_status("Fsinfo", status
, ret
);
573 /* callback function used for trans2 search */
574 static BOOL
findfirst_callback(void *private, union smb_search_data
*file
)
579 void nb_findfirst(const char *mask
, int level
, int maxcnt
, int count
, NTSTATUS status
)
581 union smb_search_first io
;
585 mem_ctx
= talloc_init("smbcli_dskattr");
587 io
.t2ffirst
.level
= level
;
588 io
.t2ffirst
.in
.max_count
= maxcnt
;
589 io
.t2ffirst
.in
.search_attrib
= FILE_ATTRIBUTE_DIRECTORY
;
590 io
.t2ffirst
.in
.pattern
= mask
;
591 io
.t2ffirst
.in
.flags
= FLAG_TRANS2_FIND_CLOSE
;
592 io
.t2ffirst
.in
.storage_type
= 0;
594 ret
= smb_raw_search_first(c
->tree
, mem_ctx
, &io
, NULL
, findfirst_callback
);
596 talloc_destroy(mem_ctx
);
598 check_status("Search", status
, ret
);
600 if (NT_STATUS_IS_OK(ret
) && io
.t2ffirst
.out
.count
!= count
) {
601 printf("[%d] Warning: got count %d expected %d\n",
603 io
.t2ffirst
.out
.count
, count
);
607 void nb_flush(int fnum
, NTSTATUS status
)
612 i
= find_handle(fnum
);
616 ret
= smb_raw_flush(c
->tree
, &io
);
618 check_status("Flush", status
, ret
);
621 void nb_sleep(int usec
, NTSTATUS status
)
627 void nb_deltree(const char *dname
)
631 smb_raw_exit(c
->session
);
634 struct ftable
*f
= ftable
;
635 DLIST_REMOVE(ftable
, f
);
639 total_deleted
= smbcli_deltree(c
->tree
, dname
);
641 if (total_deleted
== -1) {
642 printf("Failed to cleanup tree %s - exiting\n", dname
);
646 smbcli_rmdir(c
->tree
, dname
);
649 void nb_cleanup(const char *cname
)
652 asprintf(&dname
, "\\clients\\%s", cname
);
655 smbcli_rmdir(c
->tree
, "clients");
656 children
[nbio_id
].done
= 1;