From: Antonio Huete Jimenez Date: Wed, 15 Aug 2012 19:00:01 +0000 (+0200) Subject: tuxload - Enhace tuxload a bit. X-Git-Tag: v3.2.0~389 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/1923035ecf36a2a73fe11109eb2d83fefddb11ec tuxload - Enhace tuxload a bit. - Support several options (file size, number of files, multiple tests) - It can run forever via option -c --- diff --git a/test/stress/tuxload.c b/test/stress/tuxload.c index 522b93da7d..6cc1b3dcba 100644 --- a/test/stress/tuxload.c +++ b/test/stress/tuxload.c @@ -9,6 +9,7 @@ * R+W, make random modifications, and msync() in a loop. * * The purpose is to stress the VM system. + * */ #include #include @@ -17,78 +18,196 @@ #include #include #include - -#define NFILES 500 +#include static void randomfill(int fd); +static int mmap01(void *); +static int mmap02(void *); +static int build_files(void); -int -main(int argc, char *argv[]) +int opt_verbose; +int opt_testno; +int opt_nofiles; +int opt_mbfile; +int opt_count; +int fliparg; + +int *fd; +struct stat *st; +char **pp; + +static const struct test { + char testdesc[128]; + int (*testfn)(void *); +} testlist[] = { + { "mmap01 - Massive mmap / msync (flushing all pages)", mmap01 }, + { "mmap02 - Massive mmap / msync (flushing only specified pages)", mmap02 }, + { "", NULL } +}; + +static int +mmap01(void *arg) { + int i; + int *bug = arg; + long jump; + size_t size, len; - int i; - size_t size; - long jump; - int fd[NFILES]; - struct stat st[NFILES]; - char name[128]; - char *p[NFILES]; + if ((build_files()) != 0) + err(1, "Failed to create the files"); - for (i = 0; i < NFILES; i++) { - snprintf(name, 128, "tmpfiles/file%d", i); - if ((fd[i] = open(name, O_RDWR)) < 1) { - if ((fd[i] = open(name, O_RDWR | O_CREAT, 0644)) < 1) - err(1, "open"); - randomfill(fd[i]); - } - if ((fstat(fd[i], &st[i])) == -1) - err(1, "fstat"); - fprintf(stdout, "\rFile creation, random data filled [%d/%d] ", i+1, NFILES); - fflush(stdout); - } + if (opt_verbose) + printf("\n"); - printf("\n"); + for (i = 0; i < opt_nofiles; i++) { - for (i = 0; i < NFILES; i++) { - fflush(stdout); - fprintf(stdout, "\rDoing mmap() + msync() [%d/%d] ", i+1, NFILES); + if (opt_verbose) { + fflush(stdout); + fprintf(stdout, "\rDoing mmap() + msync() [%d/%d] ", i+1, opt_nofiles); + } size = st[i].st_size; - p[i] = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0); - if (p[i] == MAP_FAILED) + pp[i] = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0); + if (pp[i] == MAP_FAILED) err(1, "mmap"); for (jump = 0; jump < size; jump += 65535) { - p[i][jump] = jump + i; + pp[i][jump] = jump + i; } - /* - * This is a funny bug. MS_SYNC and 0 are reversed (i.e. - * the msync() call wasn't written correctly), but the - * broken msync() leads to a heavier VM load as a veritible - * ton of dirty file-backed pages wind up accumulating in - * the memory maps. - * - * So we leave it as is for now. - */ - if ((msync(*p, MS_SYNC, 0)) == -1) { - printf("%s: %d %p\n", name, i, *p); + if (fliparg) + len = MS_SYNC; + else + len = 0; + + if ((msync(pp[i], len, MS_SYNC)) == -1) { + printf("fd %d %p\n", fd[i], pp[i]); err(1, "msync"); } } + printf("\n"); + + return 0; +} + +static int +mmap02(void *arg) +{ + fliparg = 1; + mmap01(&fliparg); + + return 0; +} + +static void +usage(void) +{ + int i; + const struct test *tp; + + printf("tuxload: [-v] [-c count] [-m megs_per_file] [-n no_of_files] [-t test_to_run] \n" + "Available tests: \n"); + + for (tp = testlist; tp->testfn != NULL; tp++) + printf("\t%s\n", tp->testdesc); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int forever; + char c; + + opt_verbose = opt_testno = 0; + opt_nofiles = 500; + opt_mbfile = 8; + opt_count = 1; + fliparg = 0; + forever = 0; + + while ((c = getopt(argc, argv, "n:t:m:c:v")) != -1) { + switch(c) { + case 'v': + opt_verbose++; + break; + case 'n': + opt_nofiles = (int)strtol(optarg, NULL, 0); + break; + case 't': + opt_testno = (int)strtol(optarg, NULL, 0); + opt_testno--; + break; + case 'm': + opt_mbfile = (int)strtol(optarg, NULL, 0); + break; + case 'c': + opt_count = (int)strtol(optarg, NULL, 0); + if (opt_count == 0) + forever++; + break; + default: + usage(); + ; + } + } + argc -= optind; + argv += optind; + + if (argc != 0) + usage(); + + st = malloc(opt_nofiles * sizeof(*st)); + fd = malloc(opt_nofiles * sizeof(*fd)); + pp = malloc(opt_nofiles * sizeof(*pp)); + + while (opt_count-- || forever) + testlist[opt_testno].testfn(0); + return 0; } +static int +build_files(void) +{ + char name[128]; + int i; + int error; + + for (i = 0, error = 0; i < opt_nofiles; i++) { + snprintf(name, 128, "tmpfiles/file%d", i); + if ((fd[i] = open(name, O_RDWR)) < 1) { + if ((fd[i] = open(name, O_RDWR | O_CREAT, 0644)) < 1) { + error = errno; + break; + } + randomfill(fd[i]); + } + if ((fstat(fd[i], &st[i])) == -1) { + error = errno; + break; + } + if (opt_verbose) { + fprintf(stdout, "\rFile creation, random data filled [%d/%d] ", i+1, opt_nofiles); + fflush(stdout); + } + } + + return error; +} + static void randomfill(int fd) { char buf[32768]; + long tot; int i; srandomdev(); + tot = opt_mbfile * 1024L; for (i = 0; i < 32768; ++i) buf[i] = random(); - for (i = 0; i < 8192; i += 32) /* 8MB */ + for (i = 0; i < tot; i += 32) /* 8MB by default */ write(fd, buf, 32768); fsync(fd); lseek(fd, 0L, 0);