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;
39 double bytes_in, bytes_out;
44 double nbio_total(void)
48 for (i=0;i<nprocs;i++) {
49 total += children[i].bytes_out + children[i].bytes_in;
54 void nb_warmup_done(void)
56 children[nbio_id].bytes_out = 0;
57 children[nbio_id].bytes_in = 0;
64 int lines=0, num_clients=0;
67 if (nbio_id != -1) return;
69 for (i=0;i<nprocs;i++) {
70 lines += children[i].line;
71 if (!children[i].done) num_clients++;
77 printf("%4d %8d %.2f MB/sec warmup %.0f sec \r",
78 num_clients, lines/nprocs,
79 1.0e-6 * nbio_total() / t,
82 printf("%4d %8d %.2f MB/sec execute %.0f sec \r",
83 num_clients, lines/nprocs,
84 1.0e-6 * nbio_total() / t,
88 if (warmup && t >= warmup) {
95 signal(SIGALRM, nb_alarm);
99 void nbio_shmem(int n)
102 children = shm_setup(sizeof(*children) * nprocs);
104 printf("Failed to setup shared memory!\n");
109 static int find_handle(int handle)
112 children[nbio_id].line = nbench_line_count;
113 for (i=0;i<MAX_FILES;i++) {
114 if (ftable[i].handle == handle) return i;
116 printf("(%d) ERROR: handle %d was not found\n",
117 nbench_line_count, handle);
120 return -1; /* Not reached */
124 static struct cli_state *c;
126 void nb_setup(struct cli_state *cli, int id, int warmupt)
133 children[nbio_id].done = 0;
136 printf("skipping I/O\n");
140 static void check_status(const char *op, NTSTATUS status, NTSTATUS ret)
142 if (!NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(ret)) {
143 printf("[%d] Error: %s should have failed with %s\n",
144 nbench_line_count, op, nt_errstr(status));
148 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ret)) {
149 printf("[%d] Error: %s should have succeeded - %s\n",
150 nbench_line_count, op, nt_errstr(ret));
154 if (!NT_STATUS_EQUAL(status, ret)) {
155 printf("[%d] Warning: got status %s but expected %s\n",
156 nbench_line_count, nt_errstr(ret), nt_errstr(status));
161 void nb_unlink(const char *fname, int attr, NTSTATUS status)
163 struct smb_unlink io;
166 io.in.pattern = fname;
168 io.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
169 if (strchr(fname, '*') == 0) {
170 io.in.attrib |= FILE_ATTRIBUTE_DIRECTORY;
173 ret = smb_raw_unlink(c->tree, &io);
175 check_status("Unlink", status, ret);
179 void nb_createx(const char *fname,
180 unsigned create_options, unsigned create_disposition, int handle,
185 uint32 desired_access;
189 mem_ctx = talloc_init("raw_open");
191 if (create_options & NTCREATEX_OPTIONS_DIRECTORY) {
192 desired_access = SA_RIGHT_FILE_READ_DATA;
195 SA_RIGHT_FILE_READ_DATA |
196 SA_RIGHT_FILE_WRITE_DATA |
197 SA_RIGHT_FILE_READ_ATTRIBUTES |
198 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
201 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
202 io.ntcreatex.in.flags = 0;
203 io.ntcreatex.in.root_fid = 0;
204 io.ntcreatex.in.access_mask = desired_access;
205 io.ntcreatex.in.file_attr = 0;
206 io.ntcreatex.in.alloc_size = 0;
207 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE;
208 io.ntcreatex.in.open_disposition = create_disposition;
209 io.ntcreatex.in.create_options = create_options;
210 io.ntcreatex.in.impersonation = 0;
211 io.ntcreatex.in.security_flags = 0;
212 io.ntcreatex.in.fname = fname;
214 ret = smb_raw_open(c->tree, mem_ctx, &io);
216 talloc_destroy(mem_ctx);
218 if (strcmp(fname, "\\clients") != 0) {
219 check_status("NTCreateX", status, ret);
222 if (!NT_STATUS_IS_OK(ret)) return;
224 for (i=0;i<MAX_FILES;i++) {
225 if (ftable[i].handle == 0) break;
227 if (i == MAX_FILES) {
228 printf("(%d) file table full for %s\n", nbench_line_count,
232 ftable[i].handle = handle;
233 ftable[i].fd = io.ntcreatex.out.fnum;
236 void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
243 i = find_handle(handle);
245 if (bypass_io) return;
248 memset(buf, 0xab, size);
250 io.writex.level = RAW_WRITE_WRITEX;
251 io.writex.in.fnum = ftable[i].fd;
252 io.writex.in.wmode = 0;
253 io.writex.in.remaining = 0;
254 io.writex.in.offset = offset;
255 io.writex.in.count = size;
256 io.writex.in.data = buf;
258 ret = smb_raw_write(c->tree, &io);
262 check_status("WriteX", status, ret);
264 if (NT_STATUS_IS_OK(ret) && io.writex.out.nwritten != ret_size) {
265 printf("[%d] Warning: WriteX got count %d expected %d\n",
267 io.writex.out.nwritten, ret_size);
270 children[nbio_id].bytes_out += ret_size;
273 void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
280 i = find_handle(handle);
282 if (bypass_io) return;
286 memset(buf, 0x12, size);
288 io.write.level = RAW_WRITE_WRITE;
289 io.write.in.fnum = ftable[i].fd;
290 io.write.in.remaining = 0;
291 io.write.in.offset = offset;
292 io.write.in.count = size;
293 io.write.in.data = buf;
295 ret = smb_raw_write(c->tree, &io);
299 check_status("Write", status, ret);
301 if (NT_STATUS_IS_OK(ret) && io.write.out.nwritten != ret_size) {
302 printf("[%d] Warning: Write got count %d expected %d\n",
304 io.write.out.nwritten, ret_size);
307 children[nbio_id].bytes_out += ret_size;
311 void nb_lockx(int handle, unsigned offset, int size, NTSTATUS status)
316 struct smb_lock_entry lck;
318 i = find_handle(handle);
324 io.lockx.level = RAW_LOCK_LOCKX;
325 io.lockx.in.fnum = ftable[i].fd;
326 io.lockx.in.mode = 0;
327 io.lockx.in.timeout = 0;
328 io.lockx.in.ulock_cnt = 0;
329 io.lockx.in.lock_cnt = 1;
330 io.lockx.in.locks = &lck;
332 ret = smb_raw_lock(c->tree, &io);
334 check_status("LockX", status, ret);
337 void nb_unlockx(int handle, unsigned offset, int size, NTSTATUS status)
342 struct smb_lock_entry lck;
344 i = find_handle(handle);
350 io.lockx.level = RAW_LOCK_LOCKX;
351 io.lockx.in.fnum = ftable[i].fd;
352 io.lockx.in.mode = 0;
353 io.lockx.in.timeout = 0;
354 io.lockx.in.ulock_cnt = 1;
355 io.lockx.in.lock_cnt = 0;
356 io.lockx.in.locks = &lck;
358 ret = smb_raw_lock(c->tree, &io);
360 check_status("UnlockX", status, ret);
363 void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
370 i = find_handle(handle);
372 if (bypass_io) return;
376 io.readx.level = RAW_READ_READX;
377 io.readx.in.fnum = ftable[i].fd;
378 io.readx.in.offset = offset;
379 io.readx.in.mincnt = size;
380 io.readx.in.maxcnt = size;
381 io.readx.in.remaining = 0;
382 io.readx.out.data = buf;
384 ret = smb_raw_read(c->tree, &io);
388 check_status("ReadX", status, ret);
390 if (NT_STATUS_IS_OK(ret) && io.readx.out.nread != ret_size) {
391 printf("[%d] Warning: ReadX got count %d expected %d\n",
393 io.readx.out.nread, ret_size);
396 children[nbio_id].bytes_in += ret_size;
399 void nb_close(int handle, NTSTATUS status)
405 i = find_handle(handle);
407 io.close.level = RAW_CLOSE_CLOSE;
408 io.close.in.fnum = ftable[i].fd;
409 io.close.in.write_time = 0;
411 ret = smb_raw_close(c->tree, &io);
413 check_status("Close", status, ret);
415 if (NT_STATUS_IS_OK(ret)) {
416 ftable[i].handle = 0;
420 void nb_rmdir(const char *dname, NTSTATUS status)
427 ret = smb_raw_rmdir(c->tree, &io);
429 check_status("Rmdir", status, ret);
432 void nb_rename(const char *old, const char *new, NTSTATUS status)
437 io.generic.level = RAW_RENAME_RENAME;
438 io.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
439 io.rename.in.pattern1 = old;
440 io.rename.in.pattern2 = new;
442 ret = smb_raw_rename(c->tree, &io);
444 check_status("Rename", status, ret);
448 void nb_qpathinfo(const char *fname, int level, NTSTATUS status)
450 union smb_fileinfo io;
454 mem_ctx = talloc_init("nb_qpathinfo");
456 io.generic.level = level;
457 io.generic.in.fname = fname;
459 ret = smb_raw_pathinfo(c->tree, mem_ctx, &io);
461 talloc_destroy(mem_ctx);
463 check_status("Pathinfo", status, ret);
467 void nb_qfileinfo(int fnum, int level, NTSTATUS status)
469 union smb_fileinfo io;
474 i = find_handle(fnum);
476 mem_ctx = talloc_init("nb_qfileinfo");
478 io.generic.level = level;
479 io.generic.in.fnum = ftable[i].fd;
481 ret = smb_raw_fileinfo(c->tree, mem_ctx, &io);
483 talloc_destroy(mem_ctx);
485 check_status("Fileinfo", status, ret);
488 void nb_sfileinfo(int fnum, int level, NTSTATUS status)
490 union smb_setfileinfo io;
494 if (level != RAW_SFILEINFO_BASIC_INFORMATION) {
495 printf("[%d] Warning: setfileinfo level %d not handled\n", nbench_line_count, level);
501 i = find_handle(fnum);
503 io.generic.level = level;
504 io.generic.file.fnum = ftable[i].fd;
505 unix_to_nt_time(&io.basic_info.in.create_time, time(NULL));
506 unix_to_nt_time(&io.basic_info.in.access_time, 0);
507 unix_to_nt_time(&io.basic_info.in.write_time, 0);
508 unix_to_nt_time(&io.basic_info.in.change_time, 0);
509 io.basic_info.in.attrib = 0;
511 ret = smb_raw_setfileinfo(c->tree, &io);
513 check_status("Setfileinfo", status, ret);
516 void nb_qfsinfo(int level, NTSTATUS status)
522 mem_ctx = talloc_init("cli_dskattr");
524 io.generic.level = level;
525 ret = smb_raw_fsinfo(c->tree, mem_ctx, &io);
527 talloc_destroy(mem_ctx);
529 check_status("Fsinfo", status, ret);
532 /* callback function used for trans2 search */
533 static BOOL findfirst_callback(void *private, union smb_search_data *file)
538 void nb_findfirst(const char *mask, int level, int maxcnt, int count, NTSTATUS status)
540 union smb_search_first io;
544 mem_ctx = talloc_init("cli_dskattr");
546 io.t2ffirst.level = level;
547 io.t2ffirst.in.max_count = maxcnt;
548 io.t2ffirst.in.search_attrib = FILE_ATTRIBUTE_DIRECTORY;
549 io.t2ffirst.in.pattern = mask;
550 io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
551 io.t2ffirst.in.storage_type = 0;
553 ret = smb_raw_search_first(c->tree, mem_ctx, &io, NULL, findfirst_callback);
555 talloc_destroy(mem_ctx);
557 check_status("Search", status, ret);
559 if (NT_STATUS_IS_OK(ret) && io.t2ffirst.out.count != count) {
560 printf("[%d] Warning: got count %d expected %d\n",
562 io.t2ffirst.out.count, count);
566 void nb_flush(int fnum, NTSTATUS status)
571 i = find_handle(fnum);
573 io.in.fnum = ftable[i].fd;
575 ret = smb_raw_flush(c->tree, &io);
577 check_status("Flush", status, ret);
580 void nb_deltree(const char *dname)
584 smb_raw_exit(c->session);
588 total_deleted = cli_deltree(c->tree, dname);
590 if (total_deleted == -1) {
591 printf("Failed to cleanup tree %s - exiting\n", dname);
595 cli_rmdir(c->tree, dname);
598 void nb_cleanup(const char *cname)
601 asprintf(&dname, "\\clients\\%s", cname);
604 cli_rmdir(c->tree, "clients");
605 children[nbio_id].done = 1;