shithub: gefs

Download patch

ref: ecf4557d007dcd4a34433b489e382842ccf37029
parent: c7bc6cca77498f87fa9230d9628b82c46c12dba5
author: Ori Bernstein <ori@eigenstate.org>
date: Sat May 27 17:31:56 EDT 2023

freplay: add test program to replay writes to files

--- /dev/null
+++ b/test/freplay.c
@@ -1,0 +1,142 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+char*	mountpt	= "/n/replay";
+char*	logfile;
+char*	replayfile;
+char*	membuf;
+vlong	membufsz;
+vlong	replaycount = -1;
+int	logfd;
+
+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");
+	return 1;
+}
+
+void
+fsread(Req *r)
+{
+	readbuf(r, membuf, membufsz);
+	respond(r, nil);
+}
+
+void
+fswrite(Req *r)
+{
+	if(r->ifcall.offset + r->ifcall.count >= membufsz)
+		respond(r, "operation exceeds file size");
+	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);
+}
+
+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, replayfd;
+	vlong n, off;
+	char *uid;
+	File *f;
+	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;
+	default:
+		usage();
+	}ARGEND;
+	
+	if(argc != 1 || logfile == nil)
+		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 = mallocz(d->length, 1)) == nil)
+		sysfatal("failed to allocate buffer: %r");
+	for(off = 0; off < d->length; off += n)
+		if((n = read(fd, membuf+off, d->length - off)) <= 0)
+			sysfatal("read %s: short read", argv[0]);
+	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;
+		close(replayfd);
+	}
+
+	if((logfd = create(logfile, OWRITE, 0666)) == -1)
+		sysfatal("failed to open log file: %r");
+	uid = getuser();
+	fs.tree = alloctree(uid, uid, DMDIR|0555, nil);
+	f = createfile(fs.tree->root, "data", uid, 0666, nil);
+	f->length = membufsz;
+	postmountsrv(&fs, nil, mountpt, 0);
+	exits(nil);
+}