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;
38 double bytes_in, bytes_out;
43 double nbio_total(void)
47 for (i=0;i<nprocs;i++) {
48 total += children[i].bytes_out + children[i].bytes_in;
56 int lines=0, num_clients=0;
59 if (nbio_id != -1) return;
61 for (i=0;i<nprocs;i++) {
62 lines += children[i].line;
63 if (!children[i].done) num_clients++;
68 printf("%4d %8d %.2f MB/sec t=%.0f \r",
69 num_clients, lines/nprocs,
70 1.0e-6 * nbio_total() / t,
73 signal(SIGALRM, nb_alarm);
77 void nbio_shmem(int n)
80 children = shm_setup(sizeof(*children) * nprocs);
82 printf("Failed to setup shared memory!\n");
87 static int find_handle(int handle)
90 children[nbio_id].line = nbench_line_count;
91 for (i=0;i<MAX_FILES;i++) {
92 if (ftable[i].handle == handle) return i;
94 printf("(%d) ERROR: handle %d was not found\n",
95 nbench_line_count, handle);
98 return -1; /* Not reached */
102 static struct cli_state *c;
104 void nb_setup(struct cli_state *cli, int id)
110 children[nbio_id].done = 0;
113 printf("skipping I/O\n");
117 static void check_status(const char *op, NTSTATUS status, NTSTATUS ret)
119 if (!NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(ret)) {
120 printf("[%d] Error: %s should have failed with %s\n",
121 nbench_line_count, op, nt_errstr(status));
125 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ret)) {
126 printf("[%d] Error: %s should have succeeded - %s\n",
127 nbench_line_count, op, nt_errstr(ret));
131 if (!NT_STATUS_EQUAL(status, ret)) {
132 printf("[%d] Warning: got status %s but expected %s\n",
133 nbench_line_count, nt_errstr(ret), nt_errstr(status));
138 void nb_unlink(const char *fname, int attr, NTSTATUS status)
140 struct smb_unlink io;
143 io.in.pattern = fname;
145 io.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
146 if (strchr(fname, '*') == 0) {
147 io.in.attrib |= FILE_ATTRIBUTE_DIRECTORY;
150 ret = smb_raw_unlink(c->tree, &io);
152 check_status("Unlink", status, ret);
156 void nb_createx(const char *fname,
157 unsigned create_options, unsigned create_disposition, int handle,
162 uint32 desired_access;
166 mem_ctx = talloc_init("raw_open");
168 if (create_options & NTCREATEX_OPTIONS_DIRECTORY) {
169 desired_access = SA_RIGHT_FILE_READ_DATA;
172 SA_RIGHT_FILE_READ_DATA |
173 SA_RIGHT_FILE_WRITE_DATA |
174 SA_RIGHT_FILE_READ_ATTRIBUTES |
175 SA_RIGHT_FILE_WRITE_ATTRIBUTES;
178 io.ntcreatex.level = RAW_OPEN_NTCREATEX;
179 io.ntcreatex.in.flags = 0;
180 io.ntcreatex.in.root_fid = 0;
181 io.ntcreatex.in.access_mask = desired_access;
182 io.ntcreatex.in.file_attr = 0;
183 io.ntcreatex.in.alloc_size = 0;
184 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE;
185 io.ntcreatex.in.open_disposition = create_disposition;
186 io.ntcreatex.in.create_options = create_options;
187 io.ntcreatex.in.impersonation = 0;
188 io.ntcreatex.in.security_flags = 0;
189 io.ntcreatex.in.fname = fname;
191 ret = smb_raw_open(c->tree, mem_ctx, &io);
193 talloc_destroy(mem_ctx);
195 check_status("NTCreateX", status, ret);
197 if (!NT_STATUS_IS_OK(ret)) return;
199 for (i=0;i<MAX_FILES;i++) {
200 if (ftable[i].handle == 0) break;
202 if (i == MAX_FILES) {
203 printf("(%d) file table full for %s\n", nbench_line_count,
207 ftable[i].handle = handle;
208 ftable[i].fd = io.ntcreatex.out.fnum;
211 void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
218 i = find_handle(handle);
220 if (bypass_io) return;
223 memset(buf, 0xab, size);
225 io.writex.level = RAW_WRITE_WRITEX;
226 io.writex.in.fnum = ftable[i].fd;
227 io.writex.in.wmode = 0;
228 io.writex.in.remaining = 0;
229 io.writex.in.offset = offset;
230 io.writex.in.count = size;
231 io.writex.in.data = buf;
233 ret = smb_raw_write(c->tree, &io);
237 check_status("WriteX", status, ret);
239 if (io.writex.out.nwritten != ret_size) {
240 printf("[%d] Warning: WriteX got count %d expected %d\n",
242 io.writex.out.nwritten, ret_size);
245 children[nbio_id].bytes_out += ret_size;
249 void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
256 i = find_handle(handle);
258 if (bypass_io) return;
262 memset(buf, 0x12, size);
264 io.write.level = RAW_WRITE_WRITE;
265 io.write.in.fnum = ftable[i].fd;
266 io.write.in.remaining = 0;
267 io.write.in.offset = offset;
268 io.write.in.count = size;
269 io.write.in.data = buf;
271 ret = smb_raw_write(c->tree, &io);
275 check_status("Write", status, ret);
277 if (io.write.out.nwritten != ret_size) {
278 printf("[%d] Warning: Write got count %d expected %d\n",
280 io.write.out.nwritten, ret_size);
283 children[nbio_id].bytes_out += ret_size;
287 void nb_lockx(int handle, unsigned offset, int size, NTSTATUS status)
292 struct smb_lock_entry lck;
294 i = find_handle(handle);
300 io.lockx.level = RAW_LOCK_LOCKX;
301 io.lockx.in.fnum = ftable[i].fd;
302 io.lockx.in.mode = 0;
303 io.lockx.in.timeout = 0;
304 io.lockx.in.ulock_cnt = 0;
305 io.lockx.in.lock_cnt = 1;
306 io.lockx.in.locks = &lck;
308 ret = smb_raw_lock(c->tree, &io);
310 check_status("LockX", status, ret);
313 void nb_unlockx(int handle, unsigned offset, int size, NTSTATUS status)
318 struct smb_lock_entry lck;
320 i = find_handle(handle);
326 io.lockx.level = RAW_LOCK_LOCKX;
327 io.lockx.in.fnum = ftable[i].fd;
328 io.lockx.in.mode = 0;
329 io.lockx.in.timeout = 0;
330 io.lockx.in.ulock_cnt = 1;
331 io.lockx.in.lock_cnt = 0;
332 io.lockx.in.locks = &lck;
334 ret = smb_raw_lock(c->tree, &io);
336 check_status("UnlockX", status, ret);
339 void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
346 i = find_handle(handle);
348 if (bypass_io) return;
352 io.readx.level = RAW_READ_READX;
353 io.readx.in.fnum = ftable[i].fd;
354 io.readx.in.offset = offset;
355 io.readx.in.mincnt = size;
356 io.readx.in.maxcnt = size;
357 io.readx.in.remaining = 0;
358 io.readx.out.data = buf;
360 ret = smb_raw_read(c->tree, &io);
364 check_status("ReadX", status, ret);
366 if (io.readx.out.nread != ret_size) {
367 printf("[%d] Warning: ReadX got count %d expected %d\n",
369 io.readx.out.nread, ret_size);
372 children[nbio_id].bytes_in += ret_size;
375 void nb_close(int handle, NTSTATUS status)
381 i = find_handle(handle);
383 io.close.level = RAW_CLOSE_CLOSE;
384 io.close.in.fnum = ftable[i].fd;
385 io.close.in.write_time = 0;
387 ret = smb_raw_close(c->tree, &io);
389 check_status("Close", status, ret);
391 if (NT_STATUS_IS_OK(ret)) {
392 ftable[i].handle = 0;
396 void nb_rmdir(const char *dname, NTSTATUS status)
403 ret = smb_raw_rmdir(c->tree, &io);
405 check_status("Rmdir", status, ret);
408 void nb_rename(const char *old, const char *new, NTSTATUS status)
413 io.generic.level = RAW_RENAME_RENAME;
414 io.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
415 io.rename.in.pattern1 = old;
416 io.rename.in.pattern2 = new;
418 ret = smb_raw_rename(c->tree, &io);
420 check_status("Rename", status, ret);
424 void nb_qpathinfo(const char *fname, int level, NTSTATUS status)
426 union smb_fileinfo io;
430 mem_ctx = talloc_init("nb_qpathinfo");
432 io.generic.level = level;
433 io.generic.in.fname = fname;
435 ret = smb_raw_pathinfo(c->tree, mem_ctx, &io);
437 talloc_destroy(mem_ctx);
439 check_status("Pathinfo", status, ret);
443 void nb_qfileinfo(int fnum, int level, NTSTATUS status)
445 union smb_fileinfo io;
450 i = find_handle(fnum);
452 mem_ctx = talloc_init("nb_qfileinfo");
454 io.generic.level = level;
455 io.generic.in.fnum = ftable[i].fd;
457 ret = smb_raw_fileinfo(c->tree, mem_ctx, &io);
459 talloc_destroy(mem_ctx);
461 check_status("Fileinfo", status, ret);
464 void nb_sfileinfo(int fnum, int level, NTSTATUS status)
466 union smb_setfileinfo io;
470 if (level != RAW_SFILEINFO_BASIC_INFORMATION) {
471 printf("[%d] Warning: setfileinfo level %d not handled\n", nbench_line_count, level);
477 i = find_handle(fnum);
479 io.generic.level = level;
480 io.generic.file.fnum = ftable[i].fd;
481 unix_to_nt_time(&io.basic_info.in.create_time, time(NULL));
482 unix_to_nt_time(&io.basic_info.in.access_time, 0);
483 unix_to_nt_time(&io.basic_info.in.write_time, 0);
484 unix_to_nt_time(&io.basic_info.in.change_time, 0);
485 io.basic_info.in.attrib = 0;
487 ret = smb_raw_setfileinfo(c->tree, &io);
489 check_status("Setfileinfo", status, ret);
492 void nb_qfsinfo(int level, NTSTATUS status)
498 mem_ctx = talloc_init("cli_dskattr");
500 io.generic.level = level;
501 ret = smb_raw_fsinfo(c->tree, mem_ctx, &io);
503 talloc_destroy(mem_ctx);
505 check_status("Fsinfo", status, ret);
508 /* callback function used for trans2 search */
509 static BOOL findfirst_callback(void *private, union smb_search_data *file)
514 void nb_findfirst(const char *mask, int level, int maxcnt, int count, NTSTATUS status)
516 union smb_search_first io;
520 mem_ctx = talloc_init("cli_dskattr");
522 io.t2ffirst.level = level;
523 io.t2ffirst.in.max_count = maxcnt;
524 io.t2ffirst.in.search_attrib = FILE_ATTRIBUTE_DIRECTORY;
525 io.t2ffirst.in.pattern = mask;
526 io.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE;
527 io.t2ffirst.in.storage_type = 0;
529 ret = smb_raw_search_first(c->tree, mem_ctx, &io, NULL, findfirst_callback);
531 talloc_destroy(mem_ctx);
533 check_status("Search", status, ret);
535 if (io.t2ffirst.out.count != count) {
536 printf("[%d] Warning: got count %d expected %d\n",
538 io.t2ffirst.out.count, count);
542 void nb_flush(int fnum, NTSTATUS status)
547 i = find_handle(fnum);
549 io.in.fnum = ftable[i].fd;
551 ret = smb_raw_flush(c->tree, &io);
553 check_status("Flush", status, ret);
556 void nb_deltree(const char *dname)
560 smb_raw_exit(c->session);
564 total_deleted = cli_deltree(c->tree, dname);
566 if (total_deleted == -1) {
567 printf("Failed to cleanup tree %s - exiting\n", dname);
571 cli_rmdir(c->tree, dname);
574 void nb_cleanup(const char *cname)
577 asprintf(&dname, "\\clients\\%s", cname);
580 cli_rmdir(c->tree, "clients");
581 children[nbio_id].done = 1;