ref: f242ed181ff7118392737a3493e840aed9de4be1
author: Ori Bernstein <[email protected]>
date: Mon Jun 3 11:20:23 EDT 2024
initial commit: a collection of oddball scripts
--- /dev/null
+++ b/basic.rc
@@ -1,0 +1,7 @@
+#!/bin/rc -e
+
+. common.rc
+
+setup
+echo hi > $fs/test
+assert ~ `{cat $fs/test} hi
--- /dev/null
+++ b/build.rc
@@ -1,0 +1,21 @@
+#!/bin/rc -e
+
+. common.rc
+
+setup
+
+cd $fs
+
+# we don't want to clobber the installed
+# libs with something corrupt, so copy
+# them in and bind them over.
+mkdir -p $cputype/lib
+dircp /$cputype/lib $cputype/lib
+bind $cputype/lib /$cputype/lib
+
+# clone our repo
+git/clone /dist/plan9front
+bind plan9front/sys/include /sys/include
+
+cd plan9front/sys/src
+mk all
--- /dev/null
+++ b/common.rc
@@ -1,0 +1,28 @@
+#!/bin/rc
+
+rfork ne
+
+srv=gefstest.$pid
+fs=/n/$srv
+
+fn setup{
+ if(! test -f test.fs){
+ dd -if /dev/zero -of test.fs -bs 1kk -count 2k
+ chmod +t test.fs
+ }
+ ../6.out -r -f test.fs
+ ../6.out -m 32 -Au glenda -f test.fs -n $srv
+ mount -c /srv/$srv $fs
+}
+
+fn assert {
+ st=$status
+ if(! ~ $#st 0){
+ echo $st >[1=2]
+ exit $st
+ }
+}
+
+fn sigexit{
+ unmount $fs
+}
--- /dev/null
+++ b/freplay.c
@@ -1,0 +1,202 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+File* ctlfile;
+File* datfile;
+char* mountpt = "/mnt/replay";
+char* srvname = "replay";
+char* logfile;
+char* replayfile;
+char* membuf;
+vlong membufsz;
+vlong replaycount = -1;
+int logfd = -1;
+int replayfd = -1;
+vlong nwrites;
+
+void
+log1(int fd, void *buf, vlong off, vlong sz)
+{
+ char *p, hdr[12];
+
+ p = hdr;
+ PBIT64(p, off); p += 8;
+ PBIT32(p, sz);
+ if(write(fd, hdr, sizeof(hdr)) == -1)
+ sysfatal("write header: %r");
+ if(write(fd, buf, sz) == -1)
+ sysfatal("write data: %r\n");
+}
+
+int
+replay1(int fd)
+{
+ uchar *p, hdr[12];
+ vlong o;
+ int n, r;
+
+ r = readn(fd, hdr, 12);
+ if(r == 0)
+ return 0;
+ if(r != 12)
+ sysfatal("failed to read operation header: %r");
+
+ p = hdr;
+ o = GBIT64(p); p += 8;
+ n = GBIT32(p);
+ if(o + n > membufsz)
+ sysfatal("operation exceeds buffer size");
+ if(readn(fd, membuf + o, n) != n)
+ sysfatal("read op: %r");
+ nwrites++;
+ return 1;
+}
+
+void
+readmembuf(Req *r, void *s, vlong n)
+{
+ r->ofcall.count = r->ifcall.count;
+ if(r->ifcall.offset >= n){
+ r->ofcall.count = 0;
+ return;
+ }
+ if(r->ifcall.offset+r->ofcall.count > n)
+ r->ofcall.count = n - r->ifcall.offset;
+ memmove(r->ofcall.data, (char*)s+r->ifcall.offset, r->ofcall.count);
+}
+
+void
+fsread(Req *r)
+{
+ char buf[128];
+
+ if(r->fid->file == datfile){
+ readmembuf(r, membuf, membufsz);
+ respond(r, nil);
+ }else if(r->fid->file == ctlfile){
+ snprint(buf, sizeof(buf), "writes %lld\n", nwrites);
+ readstr(r, buf);
+ respond(r, nil);
+ }else
+ abort();
+}
+
+void
+fswrite(Req *r)
+{
+ if(r->fid->file == datfile){
+ if(logfile == nil){
+ respond(r, "read-only replay file: no log defined");
+ return;
+ }
+ if(r->ifcall.offset + r->ifcall.count > membufsz){
+ respond(r, "operation exceeds file size");
+ return;
+ }
+ log1(logfd, r->ifcall.data, r->ifcall.offset, r->ifcall.count);
+ memcpy(membuf + r->ifcall.offset, r->ifcall.data, r->ifcall.count);
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ nwrites++;
+ }else if(r->fid->file == ctlfile){
+ if(strncmp(r->ifcall.data, "exit", 4) == 0){
+ print("exiting...\n");
+ r->ofcall.count = r->ifcall.count;
+ respond(r, nil);
+ exits(nil);
+ }else if(strncmp(r->ifcall.data, "step", 4) == 0){
+ r->ofcall.count = r->ifcall.count;
+ if(replayfd == -1)
+ respond(r, "no active replay");
+ else if(!replay1(replayfd))
+ respond(r, "no replay left");
+ else
+ respond(r, nil);
+ }else
+ respond(r, "unknown ctl message");
+ }else
+ abort();
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-l log] [-r replay] [-c count] file\n", argv0);
+ exits("usage");
+}
+
+static Srv fs = {
+ .read = fsread,
+ .write = fswrite,
+};
+void
+main(int argc, char *argv[])
+{
+ int fd;
+ vlong n, off;
+ char *uid;
+ Dir *d;
+ int i;
+
+ ARGBEGIN{
+ case 'd':
+ chatty9p++;
+ break;
+ case 'l':
+ logfile = EARGF(usage());
+ break;
+ case 'r':
+ replayfile = EARGF(usage());
+ break;
+ case 'c':
+ replaycount = atoi(EARGF(usage()));
+ break;
+ case 'm':
+ mountpt = EARGF(usage());
+ break;
+ case 's':
+ srvname = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ if(argc != 1)
+ usage();
+
+ if((fd = open(argv[0], OREAD)) == -1)
+ sysfatal("open %s: %r", argv[0]);
+ if((d = dirfstat(fd)) == nil)
+ sysfatal("failed to stat file: %r");
+ if((membuf = sbrk(d->length)) == nil)
+ sysfatal("failed to allocate buffer: %r");
+ memset(membuf, 0, d->length);
+ for(off = 0; off < d->length; off += n)
+ if((n = read(fd, membuf+off, IOUNIT)) <= 0)
+ sysfatal("read %s@%lld: short read: %r", argv[0], off);
+ membufsz = d->length;
+ free(d);
+ if(replayfile != nil){
+ if((replayfd = open(replayfile, OREAD)) == -1)
+ sysfatal("failed to open replay file: %r");
+ for(i = 0; i < replaycount || replaycount == -1; i++)
+ if(replay1(replayfd) == 0)
+ break;
+ print("replayed %d ops\n", i);
+ }
+
+ if(logfile != nil){
+ if((logfd = create(logfile, OWRITE, 0666)) == -1)
+ sysfatal("failed to open log file: %r");
+ }
+ uid = getuser();
+ fs.tree = alloctree(uid, uid, DMDIR|0555, nil);
+ ctlfile = createfile(fs.tree->root, "ctl", uid, 0666, nil);
+ datfile = createfile(fs.tree->root, "data", uid, 0666, nil);
+ datfile->length = membufsz;
+ postmountsrv(&fs, srvname, mountpt, MREPL);
+ exits(nil);
+}
--- /dev/null
+++ b/fsbench.c
@@ -1,0 +1,518 @@
+#include <u.h>
+#include <libc.h>
+#include <libsec.h>
+#include <thread.h>
+
+int mainstacksize = 2*1024*1024;
+typedef struct Bench Bench;
+enum {
+ KiB = 1024ULL,
+ MiB = 1024ULL*KiB,
+ GiB = 1024ULL*MiB,
+ Bufsz = IOUNIT,
+};
+
+enum {
+ Bps,
+ Fps,
+};
+
+struct Bench {
+ char *name;
+ char *unit;
+ vlong (*fn)(Bench*);
+ vlong reps;
+ int nproc;
+ int id;
+ Channel *rc;
+
+ vlong i0;
+ vlong i1;
+ vlong i2;
+ char *s0;
+ char *s1;
+};
+
+#define GBIT64(p) ((u32int)(((uchar*)(p))[0]|(((uchar*)(p))[1]<<8)|\
+ (((uchar*)(p))[2]<<16)|(((uchar*)(p))[3]<<24)) |\
+ ((uvlong)(((uchar*)(p))[4]|(((uchar*)(p))[5]<<8)|\
+ (((uchar*)(p))[6]<<16)|(((uchar*)(p))[7]<<24)) << 32))
+vlong
+vrand(vlong n)
+{
+ uchar buf[8];
+ vlong slop, v;
+
+ slop = 0x7fffffffffffffffULL % n;
+ do{
+ prng(buf, 8);
+ v = GBIT64(buf);
+ }while(v <= slop);
+ return v % n;
+}
+
+vlong
+wrfile_la(Bench *b)
+{
+ char buf[Bufsz];
+ vlong i;
+ int fd;
+
+ if((fd = create(b->s0, OWRITE, 0666)) == -1)
+ sysfatal("open: %r");
+ for(i = 0; i < b->i0; i += Bufsz)
+ if(write(fd, buf, Bufsz) != Bufsz)
+ sysfatal("write: %r");
+ close(fd);
+ return b->i0/MiB;
+}
+
+vlong
+wrfile_ra(Bench *b)
+{
+ char buf[Bufsz];
+ vlong i, n, j, t, *off;
+ int fd;
+
+ n = b->i0/Bufsz;
+ if((fd = create(b->s0, OWRITE, 0666)) == -1)
+ sysfatal("open: %r");
+ if((off = malloc(n*sizeof(vlong))) == nil)
+ sysfatal("malloc: %r");
+ for(i = 0; i < n; i++)
+ off[i] = i*Bufsz;
+ for (i = n - 1; i > 0; i--) {
+ j = vrand(i+1);
+ t = off[i];
+ off[i] = off[j];
+ off[j] = t;
+ }
+ for(i = 0; i < n; i++)
+ if(pwrite(fd, buf, Bufsz, off[i]) != Bufsz)
+ sysfatal("write: %r");
+ close(fd);
+ free(off);
+ return b->i0/MiB;
+}
+
+vlong
+wrfile_rr(Bench *b)
+{
+ char buf[Bufsz];
+ vlong i, n, j, t, *off;
+ int fd;
+
+ n = b->i0/Bufsz;
+ if((fd = create(b->s0, OWRITE, 0666)) == -1)
+ sysfatal("open: %r");
+ if((off = malloc(n*sizeof(vlong))) == nil)
+ sysfatal("malloc: %r");
+ for(i = 0; i < n; i++)
+ off[i] = i*Bufsz;
+ for (i = n - 1; i > 0; i--) {
+ j = vrand(i+1);
+ t = off[i];
+ off[i] = off[j];
+ off[j] = t;
+ }
+ for(i = 0; i < n; i++)
+ if(pwrite(fd, buf, Bufsz, off[i] + vrand(100)) != Bufsz)
+ sysfatal("write: %r");
+ close(fd);
+ free(off);
+ return b->i0/MiB;
+}
+
+vlong
+rdfile_la(Bench *b)
+{
+ char path[128], buf[Bufsz];
+ vlong i, rep;
+ int fd;
+
+ if(b->id == -1)
+ snprint(path, sizeof(path), "%s", b->s0);
+ else if(b->i1 != 0)
+ snprint(path, sizeof(path), "%s.%lld", b->s0, b->id % b->i1);
+ else
+ snprint(path, sizeof(path), "%s.%d", b->s0, b->id);
+ if((fd = open(path, OREAD)) == -1)
+ sysfatal("open: %r");
+ for(rep = 0; rep < b->reps; rep++){
+ seek(fd, 0, 0);
+ for(i = 0; i < b->i0; i += Bufsz)
+ if(read(fd, buf, Bufsz) != Bufsz)
+ sysfatal("write: %r");
+ }
+ close(fd);
+ return b->reps*(b->i0/MiB);
+}
+vlong
+rdfile_ra(Bench *b)
+{
+ char path[128], buf[Bufsz];
+ vlong i, rep;
+ uvlong off;
+ int fd;
+
+ if(b->id == -1)
+ snprint(path, sizeof(path), "%s", b->s0);
+ else if(b->i1 != 0)
+ snprint(path, sizeof(path), "%s.%lld", b->s0, b->id % b->i1);
+ else
+ snprint(path, sizeof(path), "%s.%d", b->s0, b->id);
+ if((fd = open(path, OREAD)) == -1)
+ sysfatal("open: %r");
+ for(rep = 0; rep < b->reps; rep++){
+ seek(fd, 0, 0);
+ for(i = 0; i < b->i0; i += Bufsz){
+ off = vrand(b->i0-Bufsz) & ~((vlong)Bufsz-1);
+ if(pread(fd, buf, Bufsz, off) != Bufsz)
+ sysfatal("write: %r");
+ }
+ }
+ close(fd);
+ return b->reps*(b->i0/MiB);
+}
+
+vlong
+rwfile_lala(Bench *b)
+{
+ char buf[64];
+ Bench bb;
+
+ bb = *b;
+ if(b->id >= b->i1)
+ return rdfile_la(&bb);
+ else{
+ snprint(buf, sizeof(buf), "%s%d.w%d", b->s0, getpid(), b->id);
+ bb.s0 = buf;
+ return wrfile_la(&bb);
+ }
+}
+
+vlong
+rdfile_rr(Bench *b)
+{
+ char path[128], buf[Bufsz];
+ vlong i, rep;
+ uvlong off;
+ int fd;
+
+ if(b->id == -1)
+ snprint(path, sizeof(path), "%s", b->s0);
+ else if(b->i1 != 0)
+ snprint(path, sizeof(path), "%s.%lld", b->s0, b->id % b->i1);
+ else
+ snprint(path, sizeof(path), "%s.%d", b->s0, b->id);
+ if((fd = open(path, OREAD)) == -1)
+ sysfatal("open: %r");
+ for(rep = 0; rep < b->reps; rep++){
+ for(i = 0; i < b->i0; i += Bufsz){
+ off = vrand(b->i0-Bufsz);
+ if(pread(fd, buf, Bufsz, off) != Bufsz)
+ sysfatal("read: %r");
+ }
+ }
+ close(fd);
+ return b->reps*(b->i0/MiB);
+}
+
+vlong
+createflat(Bench *b)
+{
+ char buf[Bufsz];
+ int i, fd;
+
+ for(i = 0; i < b->i0; i++){
+ snprint(buf, sizeof(buf), "%s%d", b->s0, i);
+ if((fd = create(buf, OWRITE, 0666)) == -1)
+ sysfatal("create: %r");
+ if(b->i1 != 0)
+ write(fd, buf, b->i1);
+ close(fd);
+ }
+ return b->i0;
+}
+
+int
+createlevel(int n, int d)
+{
+ char buf[Bufsz];
+ int i, s, fd;
+
+ s = 0;
+ for(i = 0; i < n; i++){
+ snprint(buf, sizeof(buf), "%d", i);
+ if(d > 0){
+ if((fd = create(buf, OWRITE, 0777|DMDIR)) == -1)
+ sysfatal("create: %r");
+ if(chdir(buf) == -1)
+ sysfatal("chdir %s: %r", buf);
+ s += createlevel(n, d-1);
+ chdir("..");
+ }else{
+ if((fd = create(buf, OWRITE, 0666)) == -1)
+ sysfatal("create: %r");
+ s++;
+ }
+ close(fd);
+ }
+ return s;
+}
+
+vlong
+createhier(Bench *b)
+{
+ return createlevel(b->i0, b->i1);
+}
+
+vlong
+listfiles(Bench *b)
+{
+ char buf[Bufsz];
+ int i, r, fd;
+
+ for(i = 0; i < b->reps; i++){
+ if((fd = open(".", OREAD)) == -1)
+ sysfatal("open .: %r");
+ while(1){
+ if((r = read(fd, buf, sizeof(buf))) == -1)
+ sysfatal("read: %r");
+ if(r == 0)
+ break;
+ }
+ close(fd);
+ }
+ return b->reps*b->i0;
+}
+
+vlong
+randopen(Bench *b)
+{
+ char buf[Bufsz];
+ int i, fd;
+
+ for(i = 0; i < b->reps; i++){
+ snprint(buf, sizeof(buf), "%s%lld", b->s0, vrand(b->i0));
+ if((fd = open(buf, OREAD)) == -1)
+ sysfatal("open: %r");
+ if(b->i0)
+ if(read(fd, buf, sizeof(buf)) == -1)
+ sysfatal("read: %r");
+ close(fd);
+ }
+ return b->reps;
+}
+
+void
+launch(void *p)
+{
+ Bench *b;
+ vlong r;
+
+ b = p;
+ r = b->fn(b);
+ send(b->rc, &r);
+}
+
+vlong
+runpar(Bench *b)
+{
+ vlong r, sum;
+ Bench *sub;
+ int i;
+
+ sum = 0;
+ b->rc = chancreate(sizeof(vlong), b->nproc);
+ if((sub = calloc(b->nproc, sizeof(Bench))) == nil)
+ sysfatal("malloc: %r");
+ for(i = 0; i < b->nproc; i++){
+ sub[i] = *b;
+ sub[i].id = i;
+ proccreate(launch, &sub[i], mainstacksize);
+ }
+ for(i = 0; i < b->nproc; i++){
+ recv(b->rc, &r);
+ sum += r;
+ }
+ free(sub);
+ return sum;
+}
+
+void
+runbench(Bench *b, int nb)
+{
+ char *unit[] = {"ns", "us", "ms", "s"};
+ double oc, dt;
+ vlong t0, t1;
+ int i, j;
+
+ for(i = 0; i < nb; i++){
+ if(b[i].reps == 0)
+ b[i].reps = 1;
+ print("%20s:\t", b[i].name);
+ t0 = nsec();
+ if(b[i].nproc <= 1){
+ b[i].id = -1;
+ oc = b[i].fn(&b[i]);
+ }else
+ oc = runpar(&b[i]);
+ t1 = nsec();
+ dt = (t1 - t0);
+ for(j = 0; j < nelem(unit)-1; j++)
+ if(dt/100 < 1)
+ break;
+ else
+ dt /= 1000.0;
+ print("%f%s (%f %s/%s)\n", dt, unit[j], (double)oc/dt, b[i].unit, unit[j]);
+ }
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ Bench marks[] = {
+ /* l => linear, a => aligned, r => random */
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.0"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.1"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.2"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.3"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.4"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.5"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.6"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.7"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.8"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.9"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.10"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.11"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.12"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.13"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.14"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.15"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.16"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.17"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.18"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.19"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.20"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.21"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.22"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.23"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.24"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.25"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.26"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.27"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.28"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.29"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.30"},
+ {.name="wrcached_la", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="cached0.31"},
+
+ {.name="rdcached_lala", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0"},
+ {.name="rdcached_lara", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0"},
+ {.name="rdcached_larr", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0"},
+
+ {.name="rdcached_lala_2p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=2},
+ {.name="rdcached_lara_2p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=2},
+ {.name="rdcached_larr_2p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=2},
+
+ {.name="rdcached_lala_4p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=4},
+ {.name="rdcached_lara_4p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=4},
+ {.name="rdcached_larr_4p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=4},
+
+ {.name="rdcached_lala_8p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=8},
+ {.name="rdcached_lara_8p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=8},
+ {.name="rdcached_larr_8p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=8},
+
+ {.name="rdcached_lala_12p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=12},
+ {.name="rdcached_lara_12p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=12},
+ {.name="rdcached_larr_12p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=12},
+
+ {.name="rdcached_lala_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=16},
+ {.name="rdcached_lara_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=16},
+ {.name="rdcached_larr_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=16},
+
+ {.name="rdcached_lala_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=16},
+ {.name="rdcached_lara_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=16},
+ {.name="rdcached_larr_16p", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=16},
+
+ {.name="rdcached_lala_16p_1f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_la, .s0="cached0", .nproc=16, .i1=1},
+ {.name="rdcached_lara_16p_8f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_ra, .s0="cached0", .nproc=16, .i1=8},
+ {.name="rdcached_larr_32p_16f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=32, .i1=16},
+ {.name="rdcached_larr_32p_32f", .i0=128*MiB, .reps=2, .unit="MiB", .fn=rdfile_rr, .s0="cached0", .nproc=32, .i1=32},
+
+ {.name="wrcached_ra", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_ra, .s0="cached1"},
+ {.name="rdcached_rala", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_la, .s0="cached1"},
+ {.name="rdcached_rara", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_ra, .s0="cached1"},
+ {.name="rdcached_rarr", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_rr, .s0="cached1"},
+
+ {.name="wrcached_rr", .i0=128*MiB, .reps=1, .unit="MiB", .fn=wrfile_rr, .s0="cached2"},
+ {.name="rdcached_rrla", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_la, .s0="cached2"},
+ {.name="rdcached_rrra", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_ra, .s0="cached2"},
+ {.name="rdcached_rrrr", .i0=128*MiB, .reps=10, .unit="MiB", .fn=rdfile_rr, .s0="cached2"},
+
+ {.name="rwcached_la_r0_w2_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=2, .i1=2},
+ {.name="rwcached_la_r0_w4_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=4},
+ {.name="rwcached_la_r1_w1_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=2, .i1=1},
+ {.name="rwcached_la_r3_w1_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=1},
+ {.name="rwcached_la_r2_w2_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},
+ {.name="rwcached_la_r6_w2_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=2},
+ {.name="rwcached_la_r4_w4_w", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=4},
+
+ {.name="rwcached_la_r1_w1_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=2, .i1=1},
+ {.name="rwcached_la_r2_w1_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=3, .i1=1},
+ {.name="rwcached_la_r3_w1_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=1},
+ {.name="rwcached_la_r1_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},
+ {.name="rwcached_la_r1_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=3, .i1=2},
+ {.name="rwcached_la_r2_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},
+ {.name="rwcached_la_r4_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=4, .i1=2},
+ {.name="rwcached_la_r6_w2_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=2},
+ {.name="rwcached_la_r4_w4_r", .i0=64*MiB, .reps=10, .unit="MiB", .fn=rwfile_lala, .s0="cached0", .nproc=8, .i1=4},
+
+ {.name="createflat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .s0="cz"},
+ {.name="write1flat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .i1=1, .s0="c1"},
+ {.name="write100flat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .i1=100, .s0="c100"},
+ {.name="write1027flat", .i0=100*1000, .reps=1, .unit="files", .fn=createflat, .i1=1027, .s0="c1027"},
+ {.name="listfflat", .i0=100*1000, .reps=10, .unit="files", .fn=listfiles},
+ {.name="openfflat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .s0="cz"},
+ {.name="read0flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="cz"},
+ {.name="read1flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="c1"},
+ {.name="read100flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="c100"},
+ {.name="read1027flat", .i0=100*1000, .reps=100*1000, .unit="files", .fn=randopen, .i1=1, .s0="c1027"},
+
+// {.name="rwcached_lara", .i0=512*MiB, .reps=10, .unit="MiB", .fn=rwfile_la, .s0="cached0", .i0=1, .i1=3},
+// {.name="rwcached_la", .i0=512*MiB, .reps=10, .unit="MiB", .fn=rwfile_la, .s0="cached0", .i0=3, .i1=3},
+// {.name="rwcached_la", .i0=512*MiB, .reps=10, .unit="MiB", .fn=rwfile_la, .s0="cached0", .i0=10, .i1=10},
+
+
+ {.name="wrlarge_la", .i0=16*GiB, .reps=1, .unit="MiB", .fn=wrfile_la, .s0="large0"},
+ {.name="rdlarge_lala", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_la, .s0="large0"},
+ {.name="rdlarge_lara", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_ra, .s0="large0"},
+// {.name="rdlarge_larr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_rr, .s0="large0"},
+
+ {.name="wrlarge_ra", .i0=16*GiB, .reps=1, .unit="MiB", .fn=wrfile_ra, .s0="large1"},
+ {.name="rdlarge_lara", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_la, .s0="large1"},
+ {.name="rdlarge_rara", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_ra, .s0="large1"},
+// {.name="rdlarge_rarr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_rr, .s0="large1"},
+
+// {.name="wrlarge_rr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=wrfile_rr, .s0="large2"},
+// {.name="rdlarge_larr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_la, .s0="large2"},
+// {.name="rdlarge_rarr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_ra, .s0="large2"},
+// {.name="rdlarge_rrrr", .i0=16*GiB, .reps=1, .unit="MiB", .fn=rdfile_rr, .s0="large2"},
+
+// {.name="createheir", .i0=3, .i1=10, .reps=1, .unit="files", .fn=createhier},
+// {.name="openheir", .i0=3, .i1=10, .reps=1, .unit="files", .fn=randwalk},
+ };
+
+ ARGBEGIN{
+ }ARGEND;
+
+ if(argc != 1){
+ fprint(2, "usage: %s wdir\n", argv0);
+ exits("usage");
+ }
+ if(chdir(argv[0]) == -1)
+ sysfatal("chdir: %r");
+ runbench(marks, nelem(marks));
+ exits(nil);
+}
--- /dev/null
+++ b/grind.rc
@@ -1,0 +1,69 @@
+#!/bin/rc
+
+dev = testdev.fs
+gefs = ../$O.out
+
+fn ream {
+ mk all && 6.out -r $user -f $dev
+}
+
+fn startfs {
+ $O.out -A -f $dev
+}
+
+fn endfs {
+ kill $O.out | rc
+ while(test -f /n/gefs.grid)
+ sleep 0.1
+}
+
+fn build9 {@{
+ rfork ne
+ m
+ cd /n/gefs
+ . /sys/lib/rootstub
+ if(! test -e plan9front)
+ git/clone /dist/plan9front
+ bind -c $objtype/lib /$objtype/lib
+ bind -c plan9front/sys/include /sys/include
+ bind -c tmp /tmp
+ cd plan9front/sys/src
+ mk clean >> /tmp/log
+ mk all >> /tmp/log
+}}
+
+fn buildself {@{
+ rfork ne
+ m
+ cd /n/gefs
+ if(! test -e gefs)
+ git/clone $home/src/gefs
+ cd gefs
+ mk clean > /tmp/log
+ mk all > /tmp/log
+}}
+
+fn replay_fast {
+ ream
+ mount -c
+
+ build9
+ endfs
+}
+
+fn replay_slow {
+}
+
+fn filldisk {
+}
+
+fn lotsa9 {
+}
+
+fn lotsaself {
+}
+
+dev = testdev.fs
+rm -f $dev
+dd -if /dev/zero -of $dev -bs 1kk -count 512
+replay_fast
\ No newline at end of file
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,15 @@
+</$objtype/mkfile
+
+TESTS=\
+ basic\
+ build\
+
+all:V: 6.freplay 6.fsbench
+
+test:VQ:
+ @{cd .. && mk 6.out}
+ for(t in $TESTS){
+ echo $t...
+ ./$t.rc >[2=1] >$t.log
+ }
+</sys/src/cmd/mktest
--- /dev/null
+++ b/mkgefs.rc
@@ -1,0 +1,8 @@
+#!/bin/rc
+
+@{cd .. && mk all}
+../6.out -r $user -f $1
+../6.out -n gefs.test -A -m 2048 -f $1
+
+mount -c /srv/gefs.test /n/gefs
+mount -c /srv/gefs.test /n/gefs.adm adm
--- /dev/null
+++ b/psnap.rc
@@ -1,0 +1,45 @@
+#!/bin/rc -e
+
+
+srv=/srv/gefs
+if(~ $#* 1)
+ srv=$1
+
+fn cloneto {
+ echo clone to $1
+ @{cd /n/gefs.$1 && git/clone /dist/plan9front}
+ echo clone $1 done
+}
+
+fn buildin {
+ @{
+ rfork n
+ cd /n/gefs.$1/plan9front/
+ . /sys/lib/rootstub
+ bind -c sys/include /sys/include
+ bind -c $objtype/lib /$objtype/lib
+ bind -bc $objtype/bin /bin
+ bind -bc $objtype/bin /$objtype/bin
+ cd sys/src
+ mk all >[2=1] >/tmp/ptest.$1.log
+ }
+}
+
+echo 'create snap'
+echo 'snap -m empty test1' >> $srv.cmd
+echo 'snap -m empty test2' >> $srv.cmd
+echo 'sync' >> $srv.cmd
+mount -c $srv /n/gefs.a test1
+mount -c $srv /n/gefs.b test2
+
+echo 'clone repos'
+cloneto a &
+cloneto b &
+wait
+
+echo 'build repos'
+buildin a &
+buildin b &
+wait
+
+echo 'done'
--- /dev/null
+++ b/run.rc
@@ -1,0 +1,187 @@
+#!/bin/rc
+
+rfork ne
+
+dev=$testdev
+if(~ $#testdev 0)
+ dev = testdev.fs
+switch($cputype){
+case amd64; O=6
+case arm64; O=7
+case arm; O=5
+case 386; O=8
+}
+
+fn sigexit sigint {
+ rm -f /srv/gefs.test /srv/gefs.test.cmd /srv/replay
+}
+
+fn die {
+ echo $* >[1=2]
+ exit $"*
+}
+
+fn log {
+ echo $* >[1=2]
+}
+
+fn ge_ream {
+ $O.out -m 512 -r $user -f $1
+}
+
+fn ge_start {
+ $O.out -m 512 -A -f $1 -n gefs.test
+ while(! test -e /srv/gefs.test)
+ sleep 0.1
+ mount -c /srv/gefs.test /n/gefs
+}
+
+fn ge_kill {
+ kill $O.out | rc
+ while(test -e /srv/gefs.test)
+ sleep 0.1
+}
+
+fn ge_replay {@{
+ # prepare the test run
+ log reaming...
+ ge_ream $dev
+ log preparing replay...
+ rm -f replay.log
+ test/6.freplay -l replay.log $dev
+ ge_start /mnt/replay/data
+ $*
+ echo save trace /tmp/trace >> /srv/gefs.test.cmd
+ sleep 5
+ ge_kill
+ cat /mnt/replay/ctl
+ count=`{awk '/writes/{print $2}' /mnt/replay/ctl}
+ log did $count writes.
+ echo exit > /mnt/replay/ctl
+ while(test -e /srv/replay)
+ sleep 0.1
+
+ # check blockwise consistency
+ log starting replay...
+ test/6.freplay -c 1 -r replay.log $dev
+ for(i in `{seq 2 $count}){
+ $O.out -c -f /mnt/replay/data >[2]/tmp/log || die 'broken'
+ log stepping $i...
+ echo step > /mnt/replay/ctl
+ }
+ echo exit > /mnt/replay/ctl
+ while(test -e /srv/replay)
+ sleep 0.1
+ exit ''
+}}
+
+fn ge_ok {@{
+ # prepare the test run
+ log reaming...
+ ge_ream $dev
+ log preparing build-and-verify...
+ test/6.freplay -l replay.log $dev
+ ge_start $dev
+ $*
+ echo save trace /tmp/trace >> /srv/gefs.test.cmd
+ ge_kill
+ $O.out -c -f $dev
+}}
+
+fn buildsys{@{
+ rfork ne
+ cd /n/gefs
+ . /sys/lib/rootstub
+ if(! test -e plan9front)
+ git/clone /dist/plan9front
+ bind -c $objtype/lib /$objtype/lib
+ bind -c plan9front/sys/include /sys/include
+ bind -c tmp /tmp
+ cd plan9front/sys/src
+ mk clean >> /tmp/gefsbuild.log
+ mk all >> /tmp/gefsbuild.log
+ echo save trace >> /srv/gefs.test.cmd
+ echo check >> /srv/gefs.test.cmd
+}}
+
+fn frobsnap {@{
+ rfork ne
+ sleep 1; echo snap main x >> /srv/gefs.test.cmd
+ sleep 1; dd -if /dev/zero -of /n/gefs/file0 -bs 16k -count 128
+ sleep 1; echo snap main y >> /srv/gefs.test.cmd;
+ sleep 1; dd -if /dev/zero -of /n/gefs/file1 -bs 16k -count 128
+ sleep 1; echo snap main z >> /srv/gefs.test.cmd;
+ sleep 1; rm /n/gefs/^(file0 file1);
+ sleep 1; echo snap -d y >> /srv/gefs.test.cmd;
+ sleep 1; echo check >> /srv/gefs.test.cmd
+ sleep 1; echo snap -d z >> /srv/gefs.test.cmd;
+ sleep 1; echo check >> /srv/gefs.test.cmd
+ sleep 1; echo snap -d x >> /srv/gefs.test.cmd;
+ sleep 1; echo check >> /srv/gefs.test.cmd
+}}
+
+fn buildgo {@{
+ rfork ne
+ GOROOT=/n/gefs/go
+ GOROOT_BOOTSTRAP=/n/gefs/go-plan9-amd64-bootstrap
+ go=go1.17.13-plan9-$cputype-bootstrap
+
+ cd /n/gefs
+ if(! test -e /tmp/$go.tbz){
+ echo getting https://9legacy.org/download/go/$go.tbz ...
+ hget -o /tmp/$go.tbz https://9legacy.org/download/go/$go.tbz
+ }
+ if(! test -e $GOROOT_BOOTSTRAP){
+ echo extracting /tmp/$go.tbz ...
+ bunzip2 -c /tmp/$go.tbz | tar x >[2]/dev/null
+ }
+ mkdir go
+ mkdir tmpw
+ dircp go-plan9-amd64-bootstrap go
+ bind -c tmp /tmp
+ cd go/src
+ ./all.rc
+}}
+
+fn buildgefs {@{
+ cd /n/gefs
+ if(! test -e gefs)
+ git/clone $home/src/gefs
+ cd gefs
+ mk clean > /tmp/gefsbuild.log
+ mk all > /tmp/gefsbuild.log
+ echo check >> /srv/gefs.test.cmd
+}}
+
+fn buildgefs_slowrep {
+ for(i in `{seq $1}){
+ echo @@ buildgefs $i
+ buildgefs
+ sleep 10
+ }
+}
+
+fn fillfs {
+ dd -if /dev/zero -of /n/gefs/stuff
+}
+
+fn dotest {
+ rm -f /tmp/gefs.log /tmp/gefsbuild.log
+ echo $*
+ $* || die $status
+}
+
+if(! test -e $dev)
+ dd -if /dev/zero -of $dev -bs 1kk -count 2k
+rm -f /srv/gefs.test /srv/gefs.test.cmd /srv/replay
+mk all
+@{cd test && mk all}
+
+dotest ge_replay frobsnap
+dotest ge_replay buildgefs_slowrep 50
+dotest ge_ok buildsys
+dotest ge_ok fillfs
+
+# disabled by default: go doesn't fit into a
+# small fs; make a bigger one for testing.
+# dotest ge_ok buildgo