X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Ftests%2Ffsx.c;h=aa8aaee97ee4f803a4c7f1496877b33144e3d3c6;hb=7e7a4c9402d464d6b3e67a29a1b5c7e02acc4836;hp=af9359952070270a92d26eff5897d6e5f74950cd;hpb=fbf5870b9848929d352460f1f005b79c0b5ccc5a;p=fs%2Flustre-release.git diff --git a/lustre/tests/fsx.c b/lustre/tests/fsx.c index af93599..aa8aaee 100644 --- a/lustre/tests/fsx.c +++ b/lustre/tests/fsx.c @@ -1,6 +1,8 @@ /* * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved. * + * Copyright (c) 2012, Intel Corporation. + * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and @@ -33,7 +35,6 @@ * Sundry porting patches from Guy Harris 12/2001 * $FreeBSD: src/tools/regression/fsx/fsx.c,v 1.1 2001/12/20 04:15:57 jkh Exp $ */ - #include #include #if defined(_UWIN) || defined(__linux__) @@ -60,13 +61,33 @@ #define NUMPRINTCOLUMNS 32 /* # columns of data to print on each line */ /* + * Each test run will work with one or more separate file descriptors for the + * same file. This allows testing cache coherency across multiple mountpoints + * of the same network filesystem on a single client. + */ +struct test_file { + char *path; + int fd; +} *test_files = NULL; + +int num_test_files; +enum fd_iteration_policy { + FD_SINGLE, + FD_ROTATE, + FD_RANDOM, +}; +int fd_policy = FD_RANDOM; +int fd_last; + +/* * A log entry is an operation and a bunch of arguments. */ struct log_entry { - int operation; - struct timeval tv; - int args[3]; + int operation; + int args[3]; + struct timeval tv; + const struct test_file *tf; }; #define LOGSIZE 100000 @@ -102,15 +123,15 @@ off_t biggest = 0; char state[256]; unsigned long testcalls = 0; /* calls to function "test" */ -unsigned long simulatedopcount = 0; /* -b flag */ +long simulatedopcount = 0; /* -b flag */ int closeprob = 0; /* -c flag */ int debug = 0; /* -d flag */ -unsigned long debugstart = 0; /* -D flag */ -unsigned long maxfilelen = 256 * 1024; /* -l flag */ +long debugstart = 0; /* -D flag */ +long maxfilelen = 256 * 1024; /* -l flag */ int sizechecks = 1; /* -n flag disables them */ int maxoplen = 64 * 1024; /* -o flag */ int quiet = 0; /* -q flag */ -unsigned long progressinterval = 0; /* -p flag */ +long progressinterval = 0; /* -p flag */ int readbdy = 1; /* -r flag */ int style = 0; /* -s flag */ int truncbdy = 1; /* -t flag */ @@ -122,12 +143,12 @@ long numops = -1; /* -N flag */ int randomoplen = 1; /* -O flag disables it */ int seed = 1; /* -S flag */ int mapped_writes = 1; /* -W flag disables */ -int mapped_reads = 1; /* -R flag disables it */ +int mapped_reads = 1; /* -R flag disables it */ int fsxgoodfd = 0; +int o_direct; /* -Z */ FILE * fsxlogf = NULL; int badoff = -1; - void vwarnc(code, fmt, ap) int code; @@ -178,22 +199,42 @@ prterr(char *prefix) void -log4(int operation, int arg0, int arg1, int arg2, struct timeval *tv) +log4(int operation, int arg0, int arg1, int arg2, struct timeval *tv, + const struct test_file *tf) { struct log_entry *le; le = &oplog[logptr]; - le->tv = *tv; le->operation = operation; le->args[0] = arg0; le->args[1] = arg1; le->args[2] = arg2; + le->tv = *tv; + le->tf = tf; logptr++; logcount++; if (logptr >= LOGSIZE) logptr = 0; } +const char * +fill_tf_buf(const struct test_file *tf) +{ + static int max_tf_len; + static char tf_buf[32]; + + if (fd_policy == FD_SINGLE) + return ""; + + if (max_tf_len == 0) + max_tf_len = snprintf(tf_buf, sizeof(tf_buf) - 1, + "%u", num_test_files - 1); + + sprintf(tf_buf, "[%0*lu]", max_tf_len, + (unsigned long)(tf - test_files)); + + return tf_buf; +} void logdump(void) @@ -214,7 +255,7 @@ logdump(void) opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE; lp = &oplog[i]; - prt("%d: %lu.%06lu ", opnum, + prt("%d%s: %lu.%06lu ", opnum, fill_tf_buf(lp->tf), lp->tv.tv_sec, lp->tv.tv_usec); switch (lp->operation) { @@ -388,20 +429,6 @@ check_buffers(unsigned offset, unsigned size) } } -struct test_file { - char *path; - int fd; -} *test_files = NULL; - -int num_test_files = 0; -enum fd_iteration_policy { - FD_SINGLE, - FD_ROTATE, - FD_RANDOM, -}; -int fd_policy = FD_RANDOM; -int fd_last = 0; - struct test_file * get_tf(void) { @@ -471,8 +498,8 @@ open_test_files(char **argv, int argc) for (i = 0, tf = test_files; i < num_test_files; i++, tf++) { tf->path = argv[i]; - tf->fd = open(tf->path, O_RDWR|(lite ? 0 : O_CREAT|O_TRUNC), - 0666); + tf->fd = open(tf->path, O_RDWR|(lite ? 0 : O_CREAT|O_TRUNC)| + o_direct, 0666); if (tf->fd < 0) { prterr(tf->path); exit(91); @@ -529,8 +556,15 @@ check_trunc_hack(void) struct stat statbuf; int fd = get_fd(); - ftruncate(fd, (off_t)0); - ftruncate(fd, (off_t)100000); + /* should not ignore ftruncate(2)'s return value */ + if (ftruncate(fd, (off_t)0) < 0) { + prterr("trunc_hack: ftruncate(0)"); + exit(1); + } + if (ftruncate(fd, (off_t)100000) < 0) { + prterr("trunc_hack: ftruncate(100000)"); + exit(1); + } if (fstat(fd, &statbuf)) { prterr("trunc_hack: fstat"); statbuf.st_size = -1; @@ -539,58 +573,16 @@ check_trunc_hack(void) prt("no extend on truncate! not posix!\n"); exit(130); } - ftruncate(fd, 0); -} - -static char *tf_buf = NULL; -static int max_tf_len = 0; - -void -alloc_tf_buf(void) -{ - char dummy = '\0'; - int highest = num_test_files - 1; - int len; - - len = snprintf(&dummy, 0, "%u ", highest); - if (len < 1) { - prterr("finding max tf_buf"); - exit(1); - } - len++; - tf_buf = malloc(len); - if (tf_buf == NULL) { - prterr("allocating tf_buf"); - exit(1); - } - max_tf_len = snprintf(tf_buf, len, "%u ", highest); - if (max_tf_len < 1) { - prterr("fiding max_tv_len\n"); - exit(1); - } - if (max_tf_len != len - 1) { - warn("snprintf() gave %d instead of %d?\n", - max_tf_len, len - 1); - exit(1); - } -} - -char * -fill_tf_buf(struct test_file *tf) -{ - if (tf_buf == NULL) - alloc_tf_buf(); - - sprintf(tf_buf,"%lu ", (unsigned long)(tf - test_files)); - return tf_buf; + if (ftruncate(fd, 0) < 0) { + prterr("trunc_hack: ftruncate(0) (2nd call)"); + exit(1); + } } void output_line(struct test_file *tf, int op, unsigned offset, unsigned size, struct timeval *tv) { - char *tf_num = ""; - char *ops[] = { [OP_READ] = "read", [OP_WRITE] = "write", @@ -599,9 +591,6 @@ output_line(struct test_file *tf, int op, unsigned offset, [OP_MAPWRITE] = "mapwrite", }; - if (fd_policy != FD_SINGLE) - tf_num = fill_tf_buf(tf); - /* W. */ if (!(!quiet && ((progressinterval && testcalls % progressinterval == 0) || @@ -611,9 +600,9 @@ output_line(struct test_file *tf, int op, unsigned offset, (monitorend == -1 || offset <= monitorend))))))) return; - prt("%06lu %lu.%06lu %.*s%-10s %#08x %s %#08x\t(0x%x bytes)\n", - testcalls, tv->tv_sec, tv->tv_usec, max_tf_len, - tf_num, ops[op], + prt("%06lu%s %lu.%06lu %-10s %#08x %s %#08x\t(0x%x bytes)\n", + testcalls, fill_tf_buf(tf), tv->tv_sec, tv->tv_usec, + ops[op], offset, op == OP_TRUNCATE ? " to " : "thru", offset + size - 1, size); } @@ -628,21 +617,23 @@ doread(unsigned offset, unsigned size) int fd = tf->fd; offset -= offset % readbdy; + if (o_direct) + size -= size % readbdy; gettimeofday(&t, NULL); if (size == 0) { - if (!quiet && testcalls > simulatedopcount) + if (!quiet && testcalls > simulatedopcount && !o_direct) prt("skipping zero size read\n"); - log4(OP_SKIPPED, OP_READ, offset, size, &t); + log4(OP_SKIPPED, OP_READ, offset, size, &t, tf); return; } if (size + offset > file_size) { if (!quiet && testcalls > simulatedopcount) prt("skipping seek/read past end of file\n"); - log4(OP_SKIPPED, OP_READ, offset, size, &t); + log4(OP_SKIPPED, OP_READ, offset, size, &t, tf); return; } - log4(OP_READ, offset, size, 0, &t); + log4(OP_READ, offset, size, 0, &t, tf); if (testcalls <= simulatedopcount) return; @@ -689,17 +680,17 @@ domapread(unsigned offset, unsigned size) if (size == 0) { if (!quiet && testcalls > simulatedopcount) prt("skipping zero size read\n"); - log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t); + log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t, tf); return; } if (size + offset > file_size) { if (!quiet && testcalls > simulatedopcount) prt("skipping seek/read past end of file\n"); - log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t); + log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t, tf); return; } - log4(OP_MAPREAD, offset, size, 0, &t); + log4(OP_MAPREAD, offset, size, 0, &t, tf); if (testcalls <= simulatedopcount) return; @@ -767,15 +758,17 @@ dowrite(unsigned offset, unsigned size) int fd = tf->fd; offset -= offset % writebdy; + if (o_direct) + size -= size % writebdy; gettimeofday(&t, NULL); if (size == 0) { - if (!quiet && testcalls > simulatedopcount) + if (!quiet && testcalls > simulatedopcount && !o_direct) prt("skipping zero size write\n"); - log4(OP_SKIPPED, OP_WRITE, offset, size, &t); + log4(OP_SKIPPED, OP_WRITE, offset, size, &t, tf); return; } - log4(OP_WRITE, offset, size, file_size, &t); + log4(OP_WRITE, offset, size, file_size, &t, tf); gendata(original_buf, good_buf, offset, size); if (file_size < offset + size) { @@ -833,12 +826,12 @@ domapwrite(unsigned offset, unsigned size) if (size == 0) { if (!quiet && testcalls > simulatedopcount) prt("skipping zero size write\n"); - log4(OP_SKIPPED, OP_MAPWRITE, offset, size, &t); + log4(OP_SKIPPED, OP_MAPWRITE, offset, size, &t, tf); return; } cur_filesize = file_size; - log4(OP_MAPWRITE, offset, size, 0, &t); + log4(OP_MAPWRITE, offset, size, 0, &t, tf); gendata(original_buf, good_buf, offset, size); if (file_size < offset + size) { @@ -933,7 +926,7 @@ dotruncate(unsigned size) prt("truncating to largest ever: 0x%x\n", size); } - log4(OP_TRUNCATE, size, (unsigned)file_size, 0, &t); + log4(OP_TRUNCATE, size, (unsigned)file_size, 0, &t, tf); if (size > file_size) memset(good_buf + file_size, '\0', size - file_size); @@ -994,7 +987,7 @@ docloseopen(void) return; gettimeofday(&t, NULL); - log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t); + log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t, tf); if (debug) prt("%06lu %lu.%06lu close/open\n", testcalls, t.tv_sec, @@ -1007,7 +1000,7 @@ docloseopen(void) gettimeofday(&t, NULL); prt(" %lu.%06lu close done\n", t.tv_sec, t.tv_usec); } - tf->fd = open(tf->path, O_RDWR, 0); + tf->fd = open(tf->path, O_RDWR|o_direct, 0); if (tf->fd < 0) { prterr("docloseopen: open"); report_failure(181); @@ -1128,10 +1121,11 @@ usage(void) " -P: save .fsxlog and .fsxgood files in dirpath (default ./)\n" " -S seed: for random # generator (default 1) 0 gets timestamp\n" " -W: mapped write operations DISabled\n" -" -R: read() system calls only (mapped reads disabled)\n" -" -I: When multiple paths to the file are given each operation uses" -" a different path. Iterate through them in order with 'rotate'" -" or chose then at 'random'. (defaults to random)\n" +" -R: read() system calls only (mapped reads disabled)\n" +" -Z: O_DIRECT (use -R, -W, -r and -w too)\n" +" -I: When multiple paths to the file are given each operation uses\n" +" a different path. Iterate through them in order with 'rotate'\n" +" or chose then at 'random'. (defaults to random)\n" " fname: this filename is REQUIRED (no default)\n"); exit(90); } @@ -1186,7 +1180,7 @@ main(int argc, char **argv) setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */ while ((ch = getopt(argc, argv, - "b:c:dl:m:no:p:qr:s:t:w:D:I:LN:OP:RS:W")) + "b:c:dl:m:no:p:qr:s:t:w:D:I:LN:OP:RS:WZ")) != EOF) switch (ch) { case 'b': @@ -1307,6 +1301,9 @@ main(int argc, char **argv) if (!quiet) fprintf(stdout, "mapped writes DISABLED\n"); break; + case 'Z': + o_direct = O_DIRECT; + break; default: usage(); @@ -1367,10 +1364,36 @@ main(int argc, char **argv) original_buf = (char *) malloc(maxfilelen); for (i = 0; i < maxfilelen; i++) original_buf[i] = random() % 256; - good_buf = (char *) malloc(maxfilelen); - memset(good_buf, '\0', maxfilelen); - temp_buf = (char *) malloc(maxoplen); - memset(temp_buf, '\0', maxoplen); + if (o_direct) { + int ret; + + ret = posix_memalign((void **)&good_buf, writebdy, maxfilelen); + if (ret) { + prt("main: posix_memalign failed: %s\n", strerror(ret)); + exit(96); + } + + ret = posix_memalign((void **)&temp_buf, readbdy, maxoplen); + if (ret) { + prt("main: posix_memalign failed: %s\n", strerror(ret)); + exit(97); + } + } else { + good_buf = malloc(maxfilelen); + if (!good_buf) { + prt("malloc failed.\n"); + exit(98); + } + + temp_buf = malloc(maxoplen); + if (!temp_buf) { + prt("malloc failed.\n"); + exit(99); + } + } + memset(good_buf, 0, maxfilelen); + memset(temp_buf, 0, maxoplen); + if (lite) { /* zero entire existing file */ ssize_t written; int fd = get_fd();