/* * TUXLOAD.C * * (c)Copyright 2012 Antonio Huete Jimenez , * this code is hereby placed in the public domain. * * As a safety the directory 'tmpfiles/' must exist. This program will * create 500 x 8MB files in tmpfiles/*, memory map the files MAP_SHARED, * R+W, make random modifications, and msync() in a loop. * * The purpose is to stress the VM system. * */ #include #include #include #include #include #include #include #include static void randomfill(int fd); static int mmap01(void *); static int mmap02(void *); static int build_files(void); 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; if ((build_files()) != 0) err(1, "Failed to create the files"); if (opt_verbose) printf("\n"); for (i = 0; i < opt_nofiles; i++) { if (opt_verbose) { fflush(stdout); fprintf(stdout, "\rDoing mmap() + msync() [%d/%d] ", i+1, opt_nofiles); } size = st[i].st_size; 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) { pp[i][jump] = jump + i; } 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 < tot; i += 32) /* 8MB by default */ write(fd, buf, 32768); fsync(fd); lseek(fd, 0L, 0); }