... dump inconsistent data for further analysis during stress tests. Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com> --- contrib/stress.c | 65 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-)
diff --git a/contrib/stress.c b/contrib/stress.c index eedd9b9..27d5133 100644 --- a/contrib/stress.c +++ b/contrib/stress.c @@ -256,6 +256,7 @@ static struct fent *getfent(int which, int r) } static int testdir_fd = -1, chkdir_fd = -1; +static char *dumpfile; static int __getdents_f(unsigned int sn, struct fent *fe) { @@ -288,6 +289,47 @@ static int getdents_f(int op, unsigned int sn) return __getdents_f(sn, fe); } +static void baddump(unsigned int sn, char *buf1, char *buf2, unsigned int sz) +{ + int fd, err, i; + char *fn = dumpfile; + + if (!fn) + return; + for (i = 0;;) { + fd = open(fn, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd >= 0) { + printf("%d[%u]/%u: dump inconsistent data to \"%s\"\n", + getpid(), procid, sn, fn); + if (fn != dumpfile) + free(fn); + break; + } + if (fd < 0 && errno != EEXIST) { + fprintf(stderr, "%d[%u]/%u: failed to create dumpfile %s\n", + getpid(), procid, sn, fn); + if (fn != dumpfile) + free(fn); + return; + } + if (fn != dumpfile) + free(fn); + err = asprintf(&fn, "%s.%d", dumpfile, ++i); + if (err < 0) { + fprintf(stderr, "%d[%u]/%u: failed to allocate filename\n", + getpid(), procid, sn); + return; + } + } + if (write(fd, buf1, sz) != sz) + fprintf(stderr, "%d[%u]/%u: failed to write buffer1 @ %u", + getpid(), procid, sn, sz); + if (write(fd, buf2, sz) != sz) + fprintf(stderr, "%d[%u]/%u: failed to write buffer2 @ %u", + getpid(), procid, sn, sz); + close(fd); +} + static int readlink_f(int op, unsigned int sn) { char buf1[PATH_MAX], buf2[PATH_MAX]; @@ -317,6 +359,7 @@ static int readlink_f(int op, unsigned int sn) if (memcmp(buf1, buf2, sz)) { fprintf(stderr, "%d[%u]/%u %s: symlink mismatch @%s\n", getpid(), procid, sn, __func__, fe->subpath); + baddump(sn, buf1, buf2, sz); return -EBADMSG; } } @@ -382,8 +425,8 @@ static int __read_f(unsigned int sn, struct fent *fe, uint64_t filesize) trimmed = len <= filesize - off ? len : filesize - off; } - printf("%d[%u]/%u read_f: %llu bytes @ %llu\n", getpid(), procid, sn, - len | 0ULL, off | 0ULL); + printf("%d[%u]/%u read_f: %llu bytes @ %llu of %s\n", getpid(), procid, + sn, len | 0ULL, off | 0ULL, fe->subpath); nread = pread64(fe->fd, buf, len, off); if (nread != trimmed) { fprintf(stderr, "%d[%u]/%u read_f: failed to read %llu bytes @ %llu of %s\n", @@ -414,6 +457,7 @@ static int __read_f(unsigned int sn, struct fent *fe, uint64_t filesize) fprintf(stderr, "%d[%u]/%u read_f: data mismatch %llu bytes @ %llu of %s\n", getpid(), procid, sn, len | 0ULL, off | 0ULL, fe->subpath); + baddump(sn, buf, chkbuf, nread); return -EBADMSG; } return 0; @@ -481,6 +525,7 @@ static int __doscan_f(unsigned int sn, const char *op, struct fent *fe, fprintf(stderr, "%d[%u]/%u %s: %llu bytes mismatch @ %llu of %s\n", getpid(), procid, sn, op, chunksize | 0ULL, pos | 0ULL, fe->subpath); + baddump(sn, buf, chkbuf, nread); return -EBADMSG; } } @@ -589,7 +634,7 @@ static int parse_options(int argc, char *argv[]) char *testdir, *chkdir; int opt; - while ((opt = getopt(argc, argv, "l:p:s:")) != -1) { + while ((opt = getopt(argc, argv, "d:l:p:s:")) != -1) { switch (opt) { case 'l': loops = atoi(optarg); @@ -614,6 +659,13 @@ static int parse_options(int argc, char *argv[]) return -EINVAL; } break; + case 'd': + if (!*optarg) { + fprintf(stderr, "invalid dump file\n"); + return -EINVAL; + } + dumpfile = optarg; + break; default: /* '?' */ return -EINVAL; } @@ -650,9 +702,10 @@ static void usage(void) fputs("usage: [options] TESTDIR [COMPRDIR]\n\n" "Stress test for EROFS filesystem, where TESTDIR is the directory to test and\n" "COMPRDIR (optional) serves as a directory for data comparison.\n" - " -l# Number of times each worker should loop (0 for infinite, default: 1)\n" - " -p# Number of parallel worker processes (default: 1)\n" - " -s# Seed for random generator (default: random)\n", + " -l# Number of times each worker should loop (0 for infinite, default: 1)\n" + " -p# Number of parallel worker processes (default: 1)\n" + " -s# Seed for random generator (default: random)\n" + " -d<file> Specify a dumpfile for the inconsistent data\n", stderr); } -- 2.43.5