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.
24 #include "system/time.h"
25 #include "dlinklist.h"
29 extern int nbench_line_count;
32 static BOOL bypass_io;
36 struct ftable *next, *prev;
37 int fd; /* the fd that we got back from the server */
38 int handle; /* the handle in the load file */
41 static struct ftable *ftable;
44 double bytes_in, bytes_out;
49 double nbio_total(void)
53 for (i=0;i<nprocs;i++) {
54 total += children[i].bytes_out + children[i].bytes_in;
59 void nb_warmup_done(void)
61 children[nbio_id].bytes_out = 0;
62 children[nbio_id].bytes_in = 0;
66 void nb_alarm(int sig)
69 int lines=0, num_clients=0;
72 if (nbio_id != -1) return;
74 for (i=0;i<nprocs;i++) {
75 lines += children[i].line;
76 if (!children[i].done) num_clients++;
82 printf("%4d %8d %.2f MB/sec warmup %.0f sec \n",
83 num_clients, lines/nprocs,
84 1.0e-6 * nbio_total() / t,
87 printf("%4d %8d %.2f MB/sec execute %.0f sec \n",
88 num_clients, lines/nprocs,
89 1.0e-6 * nbio_total() / t,
93 if (warmup && t >= warmup) {
100 signal(SIGALRM, nb_alarm);
104 void nbio_shmem(int n)
107 children = shm_setup(sizeof(*children) * nprocs);
109 printf("Failed to setup shared memory!\n");
114 static struct ftable *find_ftable(int handle)
118 for (f=ftable;f;f=f->next) {
119 if (f->handle == handle) return f;
124 static int find_handle(int handle)
128 children[nbio_id].line = nbench_line_count;
130 f = find_ftable(handle);
134 printf("(%d) ERROR: handle %d was not found\n",
135 nbench_line_count, handle);
138 return -1; /* Not reached */
143 static struct smbcli_state *c;
146 a handler function for oplock break requests
148 static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private)
150 struct smbcli_tree *tree = private;
151 return smbcli_oplock_ack(tree, fnum, level);
154 void nb_setup(struct smbcli_state *cli, int id, int warmupt)
161 children[nbio_id].done = 0;
164 printf("skipping I/O\n");
167 smbcli_oplock_handler(cli->transport, oplock_handler, cli->tree);
172 static void check_status(const char *op, NTSTATUS status, NTSTATUS ret)
174 if (!NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(ret)) {
175 printf("[%d] Error: %s should have failed with %s\n",
176 nbench_line_count, op, nt_errstr(status));
180 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ret)) {
181 printf("[%d] Error: %s should have succeeded - %s\n",
182 nbench_line_count, op, nt_errstr(ret));
186 if (!NT_STATUS_EQUAL(status, ret)) {
187 printf("[%d] Warning: got status %s but expected %s\n",
188 nbench_line_count, nt_errstr(ret), nt_errstr(status));
193 void nb_unlink(const char *fname, int attr, NTSTATUS status)
195 struct smb_unlink io;
198 io.in.pattern = fname;
200 io.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
201 if (strchr(fname, '*') == 0) {
202 io.in.attrib |= FILE_ATTRIBUTE_DIRECTORY;
205 ret = smb_raw_unlink(c->tree, &io);
207 check_status("Unlink", status, ret);
211 void nb_createx(const char *fname,
212 uint_t create_options, uint_t create_disposition, int handle,
216 uint32_t desired_access;
222 mem_ctx = talloc_init("raw_open");
224 if (create_options & NTCREATEX_OPTIONS_DIRECTORY) {
225 desired_access = SA_RIGHT_FILE_READ_DATA;
228 SA_RIGHT_FILE_READ_DATA |
229 SA_RIGHT_FILE_WRITE_DATA |
230 SA_RIGHT_FILE_READ_ATTRIBUTES |
231 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
232 flags = NTCREATEX_FLAGS_EXTENDED |
233 NTCREATEX_FLAGS_REQUEST_OPLOCK |
234 NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
237 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
238 io.ntcreatex.in.flags = flags;
239 io.ntcreatex.in.root_fid = 0;
240 io.ntcreatex.in.access_mask = desired_access;
241 io.ntcreatex.in.file_attr = 0;
242 io.ntcreatex.in.alloc_size = 0;
243 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE;
244 io.ntcreatex.in.open_disposition = create_disposition;
245 io.ntcreatex.in.create_options = create_options;
246 io.ntcreatex.in.impersonation = 0;
247 io.ntcreatex.in.security_flags = 0;
248 io.ntcreatex.in.fname = fname;
250 ret = smb_raw_open(c->tree, mem_ctx, &io);
252 talloc_destroy(mem_ctx);
254 check_status("NTCreateX", status, ret);
256 if (!NT_STATUS_IS_OK(ret)) return;
258 f = malloc(sizeof(struct ftable));
260 f->fd = io.ntcreatex.out.fnum;
262 DLIST_ADD_END(ftable, f, struct ftable *);
265 void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
272 i = find_handle(handle);
274 if (bypass_io) return;
277 memset(buf, 0xab, size);
279 io.writex.level = RAW_WRITE_WRITEX;
280 io.writex.in.fnum = i;
281 io.writex.in.wmode = 0;
282 io.writex.in.remaining = 0;
283 io.writex.in.offset = offset;
284 io.writex.in.count = size;
285 io.writex.in.data = buf;
287 ret = smb_raw_write(c->tree, &io);
291 check_status("WriteX", status, ret);
293 if (NT_STATUS_IS_OK(ret) && io.writex.out.nwritten != ret_size) {
294 printf("[%d] Warning: WriteX got count %d expected %d\n",
296 io.writex.out.nwritten, ret_size);
299 children[nbio_id].bytes_out += ret_size;
302 void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
309 i = find_handle(handle);
311 if (bypass_io) return;
315 memset(buf, 0x12, size);
317 io.write.level = RAW_WRITE_WRITE;
318 io.write.in.fnum = i;
319 io.write.in.remaining = 0;
320 io.write.in.offset = offset;
321 io.write.in.count = size;
322 io.write.in.data = buf;
324 ret = smb_raw_write(c->tree, &io);
328 check_status("Write", status, ret);
330 if (NT_STATUS_IS_OK(ret) && io.write.out.nwritten != ret_size) {
331 printf("[%d] Warning: Write got count %d expected %d\n",
333 io.write.out.nwritten, ret_size);
336 children[nbio_id].bytes_out += ret_size;
340 void nb_lockx(int handle, uint_t offset, int size, NTSTATUS status)
345 struct smb_lock_entry lck;
347 i = find_handle(handle);
353 io.lockx.level = RAW_LOCK_LOCKX;
354 io.lockx.in.fnum = i;
355 io.lockx.in.mode = 0;
356 io.lockx.in.timeout = 0;
357 io.lockx.in.ulock_cnt = 0;
358 io.lockx.in.lock_cnt = 1;
359 io.lockx.in.locks = &lck;
361 ret = smb_raw_lock(c->tree, &io);
363 check_status("LockX", status, ret);
366 void nb_unlockx(int handle, uint_t offset, int size, NTSTATUS status)
371 struct smb_lock_entry lck;
373 i = find_handle(handle);
379 io.lockx.level = RAW_LOCK_LOCKX;
380 io.lockx.in.fnum = i;
381 io.lockx.in.mode = 0;
382 io.lockx.in.timeout = 0;
383 io.lockx.in.ulock_cnt = 1;
384 io.lockx.in.lock_cnt = 0;
385 io.lockx.in.locks = &lck;
387 ret = smb_raw_lock(c->tree, &io);
389 check_status("UnlockX", status, ret);
392 void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
399 i = find_handle(handle);
401 if (bypass_io) return;
405 io.readx.level = RAW_READ_READX;
406 io.readx.in.fnum = i;
407 io.readx.in.offset = offset;
408 io.readx.in.mincnt = size;
409 io.readx.in.maxcnt = size;
410 io.readx.in.remaining = 0;
411 io.readx.out.data = buf;
413 ret = smb_raw_read(c->tree, &io);
417 check_status("ReadX", status, ret);
419 if (NT_STATUS_IS_OK(ret) && io.readx.out.nread != ret_size) {
420 printf("[%d] ERROR: ReadX got count %d expected %d\n",
422 io.readx.out.nread, ret_size);
426 children[nbio_id].bytes_in += ret_size;
429 void nb_close(int handle, NTSTATUS status)
435 i = find_handle(handle);
437 io.close.level = RAW_CLOSE_CLOSE;
438 io.close.in.fnum = i;
439 io.close.in.write_time = 0;
441 ret = smb_raw_close(c->tree, &io);
443 check_status("Close", status, ret);
445 if (NT_STATUS_IS_OK(ret)) {
446 struct ftable *f = find_ftable(handle);
447 DLIST_REMOVE(ftable, f);
452 void nb_rmdir(const char *dname, NTSTATUS status)
459 ret = smb_raw_rmdir(c->tree, &io);
461 check_status("Rmdir", status, ret);
464 void nb_mkdir(const char *dname, NTSTATUS status)
468 io.mkdir.level = RAW_MKDIR_MKDIR;
469 io.mkdir.in.path = dname;
471 /* NOTE! no error checking. Used for base fileset creation */
472 smb_raw_mkdir(c->tree, &io);
475 void nb_rename(const char *old, const char *new, NTSTATUS status)
480 io.generic.level = RAW_RENAME_RENAME;
481 io.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
482 io.rename.in.pattern1 = old;
483 io.rename.in.pattern2 = new;
485 ret = smb_raw_rename(c->tree, &io);
487 check_status("Rename", status, ret);
491 void nb_qpathinfo(const char *fname, int level, NTSTATUS status)
493 union smb_fileinfo io;
497 mem_ctx = talloc_init("nb_qpathinfo");
499 io.generic.level = level;
500 io.generic.in.fname = fname;
502 ret = smb_raw_pathinfo(c->tree, mem_ctx, &io);
504 talloc_destroy(mem_ctx);
506 check_status("Pathinfo", status, ret);
510 void nb_qfileinfo(int fnum, int level, NTSTATUS status)
512 union smb_fileinfo io;
517 i = find_handle(fnum);
519 mem_ctx = talloc_init("nb_qfileinfo");
521 io.generic.level = level;
522 io.generic.in.fnum = i;
524 ret = smb_raw_fileinfo(c->tree, mem_ctx, &io);
526 talloc_destroy(mem_ctx);
528 check_status("Fileinfo", status, ret);
531 void nb_sfileinfo(int fnum, int level, NTSTATUS status)
533 union smb_setfileinfo io;
537 if (level != RAW_SFILEINFO_BASIC_INFORMATION) {
538 printf("[%d] Warning: setfileinfo level %d not handled\n", nbench_line_count, level);
544 i = find_handle(fnum);
546 io.generic.level = level;
547 io.generic.file.fnum = i;
548 unix_to_nt_time(&io.basic_info.in.create_time, time(NULL));
549 unix_to_nt_time(&io.basic_info.in.access_time, 0);
550 unix_to_nt_time(&io.basic_info.in.write_time, 0);
551 unix_to_nt_time(&io.basic_info.in.change_time, 0);
552 io.basic_info.in.attrib = 0;
554 ret = smb_raw_setfileinfo(c->tree, &io);
556 check_status("Setfileinfo", status, ret);
559 void nb_qfsinfo(int level, NTSTATUS status)
565 mem_ctx = talloc_init("smbcli_dskattr");
567 io.generic.level = level;
568 ret = smb_raw_fsinfo(c->tree, mem_ctx, &io);
570 talloc_destroy(mem_ctx);
572 check_status("Fsinfo", status, ret);
575 /* callback function used for trans2 search */
576 static BOOL findfirst_callback(void *private, union smb_search_data *file)
581 void nb_findfirst(const char *mask, int level, int maxcnt, int count, NTSTATUS status)
583 union smb_search_first io;
587 mem_ctx = talloc_init("smbcli_dskattr");
589 io.t2ffirst.level = level;
590 io.t2ffirst.in.max_count = maxcnt;
591 io.t2ffirst.in.search_attrib = FILE_ATTRIBUTE_DIRECTORY;
592 io.t2ffirst.in.pattern = mask;
593 io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
594 io.t2ffirst.in.storage_type = 0;
596 ret = smb_raw_search_first(c->tree, mem_ctx, &io, NULL, findfirst_callback);
598 talloc_destroy(mem_ctx);
600 check_status("Search", status, ret);
602 if (NT_STATUS_IS_OK(ret) && io.t2ffirst.out.count != count) {
603 printf("[%d] Warning: got count %d expected %d\n",
605 io.t2ffirst.out.count, count);
609 void nb_flush(int fnum, NTSTATUS status)
614 i = find_handle(fnum);
618 ret = smb_raw_flush(c->tree, &io);
620 check_status("Flush", status, ret);
623 void nb_sleep(int usec, NTSTATUS status)
629 void nb_deltree(const char *dname)
633 smb_raw_exit(c->session);
636 struct ftable *f = ftable;
637 DLIST_REMOVE(ftable, f);
641 total_deleted = smbcli_deltree(c->tree, dname);
643 if (total_deleted == -1) {
644 printf("Failed to cleanup tree %s - exiting\n", dname);
648 smbcli_rmdir(c->tree, dname);
651 void nb_cleanup(const char *cname)
654 asprintf(&dname, "\\clients\\%s", cname);
657 smbcli_rmdir(c->tree, "clients");
658 children[nbio_id].done = 1;