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 check_status("NTCreateX", status, ret);
220 if (!NT_STATUS_IS_OK(ret)) return;
222 for (i=0;i<MAX_FILES;i++) {
223 if (ftable[i].handle == 0) break;
225 if (i == MAX_FILES) {
226 printf("(%d) file table full for %s\n", nbench_line_count,
230 ftable[i].handle = handle;
231 ftable[i].fd = io.ntcreatex.out.fnum;
234 void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
241 i = find_handle(handle);
243 if (bypass_io) return;
246 memset(buf, 0xab, size);
248 io.writex.level = RAW_WRITE_WRITEX;
249 io.writex.in.fnum = ftable[i].fd;
250 io.writex.in.wmode = 0;
251 io.writex.in.remaining = 0;
252 io.writex.in.offset = offset;
253 io.writex.in.count = size;
254 io.writex.in.data = buf;
256 ret = smb_raw_write(c->tree, &io);
260 check_status("WriteX", status, ret);
262 if (NT_STATUS_IS_OK(ret) && io.writex.out.nwritten != ret_size) {
263 printf("[%d] Warning: WriteX got count %d expected %d\n",
265 io.writex.out.nwritten, ret_size);
268 children[nbio_id].bytes_out += ret_size;
271 void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
278 i = find_handle(handle);
280 if (bypass_io) return;
284 memset(buf, 0x12, size);
286 io.write.level = RAW_WRITE_WRITE;
287 io.write.in.fnum = ftable[i].fd;
288 io.write.in.remaining = 0;
289 io.write.in.offset = offset;
290 io.write.in.count = size;
291 io.write.in.data = buf;
293 ret = smb_raw_write(c->tree, &io);
297 check_status("Write", status, ret);
299 if (NT_STATUS_IS_OK(ret) && io.write.out.nwritten != ret_size) {
300 printf("[%d] Warning: Write got count %d expected %d\n",
302 io.write.out.nwritten, ret_size);
305 children[nbio_id].bytes_out += ret_size;
309 void nb_lockx(int handle, unsigned offset, int size, NTSTATUS status)
314 struct smb_lock_entry lck;
316 i = find_handle(handle);
322 io.lockx.level = RAW_LOCK_LOCKX;
323 io.lockx.in.fnum = ftable[i].fd;
324 io.lockx.in.mode = 0;
325 io.lockx.in.timeout = 0;
326 io.lockx.in.ulock_cnt = 0;
327 io.lockx.in.lock_cnt = 1;
328 io.lockx.in.locks = &lck;
330 ret = smb_raw_lock(c->tree, &io);
332 check_status("LockX", status, ret);
335 void nb_unlockx(int handle, unsigned offset, int size, NTSTATUS status)
340 struct smb_lock_entry lck;
342 i = find_handle(handle);
348 io.lockx.level = RAW_LOCK_LOCKX;
349 io.lockx.in.fnum = ftable[i].fd;
350 io.lockx.in.mode = 0;
351 io.lockx.in.timeout = 0;
352 io.lockx.in.ulock_cnt = 1;
353 io.lockx.in.lock_cnt = 0;
354 io.lockx.in.locks = &lck;
356 ret = smb_raw_lock(c->tree, &io);
358 check_status("UnlockX", status, ret);
361 void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
368 i = find_handle(handle);
370 if (bypass_io) return;
374 io.readx.level = RAW_READ_READX;
375 io.readx.in.fnum = ftable[i].fd;
376 io.readx.in.offset = offset;
377 io.readx.in.mincnt = size;
378 io.readx.in.maxcnt = size;
379 io.readx.in.remaining = 0;
380 io.readx.out.data = buf;
382 ret = smb_raw_read(c->tree, &io);
386 check_status("ReadX", status, ret);
388 if (NT_STATUS_IS_OK(ret) && io.readx.out.nread != ret_size) {
389 printf("[%d] Warning: ReadX got count %d expected %d\n",
391 io.readx.out.nread, ret_size);
394 children[nbio_id].bytes_in += ret_size;
397 void nb_close(int handle, NTSTATUS status)
403 i = find_handle(handle);
405 io.close.level = RAW_CLOSE_CLOSE;
406 io.close.in.fnum = ftable[i].fd;
407 io.close.in.write_time = 0;
409 ret = smb_raw_close(c->tree, &io);
411 check_status("Close", status, ret);
413 if (NT_STATUS_IS_OK(ret)) {
414 ftable[i].handle = 0;
418 void nb_rmdir(const char *dname, NTSTATUS status)
425 ret = smb_raw_rmdir(c->tree, &io);
427 check_status("Rmdir", status, ret);
430 void nb_mkdir(const char *dname, NTSTATUS status)
434 io.mkdir.level = RAW_MKDIR_MKDIR;
435 io.mkdir.in.path = dname;
437 /* NOTE! no error checking. Used for base fileset creation */
438 smb_raw_mkdir(c->tree, &io);
441 void nb_rename(const char *old, const char *new, NTSTATUS status)
446 io.generic.level = RAW_RENAME_RENAME;
447 io.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
448 io.rename.in.pattern1 = old;
449 io.rename.in.pattern2 = new;
451 ret = smb_raw_rename(c->tree, &io);
453 check_status("Rename", status, ret);
457 void nb_qpathinfo(const char *fname, int level, NTSTATUS status)
459 union smb_fileinfo io;
463 mem_ctx = talloc_init("nb_qpathinfo");
465 io.generic.level = level;
466 io.generic.in.fname = fname;
468 ret = smb_raw_pathinfo(c->tree, mem_ctx, &io);
470 talloc_destroy(mem_ctx);
472 check_status("Pathinfo", status, ret);
476 void nb_qfileinfo(int fnum, int level, NTSTATUS status)
478 union smb_fileinfo io;
483 i = find_handle(fnum);
485 mem_ctx = talloc_init("nb_qfileinfo");
487 io.generic.level = level;
488 io.generic.in.fnum = ftable[i].fd;
490 ret = smb_raw_fileinfo(c->tree, mem_ctx, &io);
492 talloc_destroy(mem_ctx);
494 check_status("Fileinfo", status, ret);
497 void nb_sfileinfo(int fnum, int level, NTSTATUS status)
499 union smb_setfileinfo io;
503 if (level != RAW_SFILEINFO_BASIC_INFORMATION) {
504 printf("[%d] Warning: setfileinfo level %d not handled\n", nbench_line_count, level);
510 i = find_handle(fnum);
512 io.generic.level = level;
513 io.generic.file.fnum = ftable[i].fd;
514 unix_to_nt_time(&io.basic_info.in.create_time, time(NULL));
515 unix_to_nt_time(&io.basic_info.in.access_time, 0);
516 unix_to_nt_time(&io.basic_info.in.write_time, 0);
517 unix_to_nt_time(&io.basic_info.in.change_time, 0);
518 io.basic_info.in.attrib = 0;
520 ret = smb_raw_setfileinfo(c->tree, &io);
522 check_status("Setfileinfo", status, ret);
525 void nb_qfsinfo(int level, NTSTATUS status)
531 mem_ctx = talloc_init("cli_dskattr");
533 io.generic.level = level;
534 ret = smb_raw_fsinfo(c->tree, mem_ctx, &io);
536 talloc_destroy(mem_ctx);
538 check_status("Fsinfo", status, ret);
541 /* callback function used for trans2 search */
542 static BOOL findfirst_callback(void *private, union smb_search_data *file)
547 void nb_findfirst(const char *mask, int level, int maxcnt, int count, NTSTATUS status)
549 union smb_search_first io;
553 mem_ctx = talloc_init("cli_dskattr");
555 io.t2ffirst.level = level;
556 io.t2ffirst.in.max_count = maxcnt;
557 io.t2ffirst.in.search_attrib = FILE_ATTRIBUTE_DIRECTORY;
558 io.t2ffirst.in.pattern = mask;
559 io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
560 io.t2ffirst.in.storage_type = 0;
562 ret = smb_raw_search_first(c->tree, mem_ctx, &io, NULL, findfirst_callback);
564 talloc_destroy(mem_ctx);
566 check_status("Search", status, ret);
568 if (NT_STATUS_IS_OK(ret) && io.t2ffirst.out.count != count) {
569 printf("[%d] Warning: got count %d expected %d\n",
571 io.t2ffirst.out.count, count);
575 void nb_flush(int fnum, NTSTATUS status)
580 i = find_handle(fnum);
582 io.in.fnum = ftable[i].fd;
584 ret = smb_raw_flush(c->tree, &io);
586 check_status("Flush", status, ret);
589 void nb_deltree(const char *dname)
593 smb_raw_exit(c->session);
597 total_deleted = cli_deltree(c->tree, dname);
599 if (total_deleted == -1) {
600 printf("Failed to cleanup tree %s - exiting\n", dname);
604 cli_rmdir(c->tree, dname);
607 void nb_cleanup(const char *cname)
610 asprintf(&dname, "\\clients\\%s", cname);
613 cli_rmdir(c->tree, "clients");
614 children[nbio_id].done = 1;