code: mafs

Download patch

ref: 322ee5ed143f7655d4c3282bf4cf16d5b6c812e3
parent: 6e2e8c58342a6b3bba516d0ee42107a54d4c7717
author: 9ferno <gophone2015@gmail.com>
date: Wed Nov 9 03:44:43 EST 2022

added mfs for a file system with synchronous writes

--- a/iobuf.c
+++ b/iobuf.c
@@ -3,6 +3,7 @@
 u64  nbuckets = 0;	/* number of hash buckets, -m changes it */
 Hiob *hiob = nil;	/* array of nbuckets */
 Extents frees = {0};/* extents of free blocks on the disk */
+extern u8 synchronouswrites;
 
 /*
 	extents of Rawblocksize units of memory used to store
@@ -302,7 +303,15 @@
 			p->blkno == config.root.srcbno){
 			memcpy(buf, p->io->buf, Blocksize);
 		}
-		putwrite(p);
+		if(synchronouswrites){
+			if(devwrite(p->blkno, p->xiobuf) != Rawblocksize)
+				panic("putbuf: could not write block\n");
+			if(chkwunlock(p) == 0){
+				showbuf(p);
+				panic("putbuf: chkwunlock(p) == 0 called by %#p\n", getcallerpc(&p));
+			}
+		} else
+			putwrite(p);
 		if(srcbno == config.config.srcbno){
 			for(i=0; i<Nbkp; i++)
 				bkp(srcbno, buf, config.config.dest[i], Qpconfig0+i*3);
@@ -319,7 +328,23 @@
 void
 putbufs(Iobuf **ps, u64 len)
 {
-	putwrites(ps, len);
+	u64 wn, i;
+	u8 *jumbo;
+
+	if(synchronouswrites){
+		jumbo = emalloc9p(len*Rawblocksize);
+		for(i = 0; i < len; i++)
+			memcpy(jumbo+(i*Rawblocksize), ps[i]->xiobuf, Rawblocksize);
+		if((wn = devwrites(ps[0]->blkno, jumbo, len)) != len*Rawblocksize){
+			dprint("%s\n", errstring[Esystem]);
+			panic("error writing jumbo block %llud: %llud bytes, written %llud: %r\n",
+					ps[0]->blkno, len, wn);
+		}
+		free(jumbo);
+		for(i = 0; i < len; i++)
+			wunlock(ps[i]);
+	}else
+		putwrites(ps, len);
 }
 
 /* only caller is freeblockbuf().
--- a/mafs.c
+++ b/mafs.c
@@ -19,6 +19,7 @@
 u8	noauth = 0;
 u8	readonly = 0;
 u8	shuttingdown = 0;
+u8	synchronouswrites = 0;
 extern u64 npendingwrites;		/* write throttling */
 
 int	writeallow;	/* never on; for compatibility with fs */
--- /dev/null
+++ b/mfs.c
@@ -1,0 +1,253 @@
+#include	"all.h"
+#include	"pool.h"
+
+int	sfd;
+int	cmdmode = 0660;
+int	rfd;
+int	chat;
+
+Uid*	uid;
+char*	uidspace;
+short*	gidspace;
+RWLock	mainlock;
+Tlock	*tlocks;
+char	*progname;
+char	*procname;
+
+char *devfile = nil;	/* device file path */
+char service[Namelen] = "\0";
+u8	noauth = 0;
+u8	readonly = 0;
+u8	shuttingdown = 0;
+u8	synchronouswrites = 1;
+
+int	writeallow;	/* never on; for compatibility with fs */
+int	wstatallow;
+int	writegroup;
+int	allownone;
+static void	usage(void);
+static void	printsizes(void);
+static u64	memsize(void);
+Config config = {0};
+
+static void
+usage(void)
+{
+	fprint(2, "usage: mfs [-Ds] [-r service] [-n service] [-m nmemunits] [-h nbuckets] [-a announce-string]... file\n");
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	static char *nets[8];
+	int doream, stdio, netc;
+	char buf[Namelen];
+	int pid, ctl;
+	u64 nmemunits, size;
+
+	progname = "mafs";
+	procname = "init";
+
+	/* mainmem->flags |= POOL_PARANOIA|POOL_LOGGING; */
+
+	/*
+	 * insulate from invoker's environment and keep it from swapping
+	 */
+	rfork(RFNAMEG|RFNOTEG|RFREND);
+
+	nbuckets = 0;
+	nmemunits = 0;
+	sfd = -1;
+	doream = stdio = netc = 0;
+
+	pid = getpid();
+	snprint(buf, sizeof buf, "/proc/%d/ctl", pid);
+	ctl = open(buf, OWRITE);
+	fprint(ctl, "noswap\n");
+	close(ctl);
+
+	ARGBEGIN{
+	default:	usage();
+	case 'D':	chatty9p++; break;
+	case 'f':	devfile = ARGF(); break;
+	case 'h':	nbuckets = atoll(EARGF(usage())); break;
+	case 'm':	nmemunits = atoll(EARGF(usage())); break;
+	case 'r':
+		doream = 1;
+		/* fall through */
+	case 'n':
+		snprint(service, Namelen, "%s", EARGF(usage()));
+		break;
+	case 's':	stdio++;    break;
+	case 'a':
+		if(netc >= nelem(nets)-1){
+			fprint(2, "%s: too many networks to announce\n", argv0);
+			exits("too many nets");
+		}
+		nets[netc++] = estrdup9p(EARGF(usage()));
+		break;
+	}ARGEND
+
+	if(argc != 1 || (doream && service[0] == '\0'))
+		usage();
+
+	devfile = argv[0];
+	if(devfile == nil)
+		sysfatal("no disk file");
+
+	if (access(devfile, AREAD|AWRITE) == -1)
+		sysfatal("%s cannot access device", devfile);
+
+	size = devinit(devfile);
+	if(size == 0)
+		panic("null size %s", devfile);
+
+	/* 2/3rds of the memory for the pending writes
+		and 1/3rd for the buffer cache
+		leaving 4*(Iounit/Blocksize) for jumbo writes
+	 */
+	if(nmemunits == 0)
+		nmemunits = size/Rawblocksize > 8*MiB ? 8*MiB : size/Rawblocksize;
+	if(nmemunits < KiB)
+		nmemunits = KiB;
+	if(nbuckets == 0)
+		nbuckets = nmemunits/(3*Ncollisions);
+
+	if(chatty9p){
+		dprint("\nPlan 9 %d-bit file server with %d-deep indirect blocks\n",
+			sizeof(u64)*8, Niblock);
+		printsizes();
+		dprint("nmemunits %llud nbuckets %llud\n",
+				nmemunits, nbuckets);
+	}
+
+	formatinit();
+
+	initmemunitpool(nmemunits);
+	initextents(&frees);
+
+	tlocks = emalloc9p(NTLOCK * sizeof *tlocks);
+	iobufinit();
+
+	/*
+	 * init the file system, ream it if needed, and get the block sizes.
+	 * service = config.service, if service is nil.
+	 */
+	init(doream, size);
+	if(service[0] == '\0')
+		snprint(service, Namelen, "%s", config.service);
+
+	start9p(nets, stdio);
+	/*
+		we have started another proc to process /srv/service
+		and it is my time to exit
+	 */
+	exits(nil);
+}
+
+static
+struct
+{
+	int	nfilter;
+	Filter*	filters[100];
+}f;
+
+int alarmed;
+
+void
+catchalarm(void *regs, char *msg)
+{
+	USED(regs, msg);
+	if(strcmp(msg, "alarm") == 0){
+		alarmed = 1;
+		noted(NCONT);
+	} else
+		noted(NDFLT);
+}
+
+void
+dofilter(Filter *ft)
+{
+	int i;
+
+	i = f.nfilter;
+	if(i >= sizeof f.filters / sizeof f.filters[0]) {
+		dprint("dofilter: too many filters\n");
+		return;
+	}
+	f.filters[i] = ft;
+	f.nfilter = i+1;
+}
+
+static u64
+memsize(void)
+{
+	char *p, buf[128];
+	int fd, n, by2pg, secs;
+
+	by2pg = 4*1024;
+	p = getenv("cputype");
+	if(p && strcmp(p, "68020") == 0)
+		by2pg = 8*1024;
+
+	secs = 4*1024*1024;
+	
+	fd = open("/dev/swap", OREAD);
+	if(fd < 0)
+		return secs;
+	n = read(fd, buf, sizeof(buf)-1);
+	close(fd);
+	if(n <= 0)
+		return secs;
+	buf[n] = 0;
+	p = strchr(buf, '/');
+	if(p)
+		secs = strtoul(p+1, 0, 0)*by2pg;
+	return secs;
+}
+
+/*
+ * compute BUFSIZE*(Ndblock+INDPERBUF+INDPERBUF²+INDPERBUF³+INDPERBUF⁴ .. upto ^Niblock)
+ * while watching for overflow; in that case, return 0.
+ */
+
+static u64
+maxsize(void)
+{
+	int i;
+	uvlong max = Ndblock, ind;
+
+	dprint("maxsize direct spans max %llud\n", max);
+	for (i = 0; i < Niblock; i++) {
+		ind = nperiblock(Tind0+i);
+		max += ind;
+		dprint("maxsize %s %llud max %llud\n", tagnames[Tind0+i], ind, max);
+	}
+	return max;
+}
+
+/* also in tests/sizes.c */
+static void
+printsizes(void)
+{
+	int i;
+	u64 n, max;
+
+	dprint("Namelen %d Ndblock %d Niblock %d\n", Namelen, Ndblock, Niblock);
+	dprint("Blocksize %d Nindperblock %d\n",
+			Blocksize, Nindperblock);
+
+	for (i = Tind0; i < Maxtind; i++) {
+		n = nperindunit(i);
+		dprint("A %s unit points to %lld data spans (%llud bytes)\n",
+			 tagnames[i], n, n*Blocksize);
+		dprint("	block points to %lld data spans\n", nperiblock(i));
+	}
+	dprint("sizeof(Dentry1) %d Namelen %d\n",
+			sizeof(Dentry1), Namelen);
+	max = maxsize();
+	dprint("maximum possible spans %llud\n", max);
+	dprint("	(%llud*Rawblocksize = %llud bytes = %llud TiB)\n",
+			max, max*Rawblocksize, (max*Rawblocksize)/(MiB*MiB));
+}
--- a/mkfile
+++ b/mkfile
@@ -1,6 +1,6 @@
 </$objtype/mkfile
 
-TARG=mafs used reconcile block find free unused updatefrees
+TARG=mfs mafs used reconcile block find free unused updatefrees
 
 OFILES=\
 	9p.$O\
--- a/writer.c
+++ b/writer.c
@@ -234,8 +234,8 @@
 			}
 			if((wn = devwrites(startblkno, jumbo, n)) != n*Rawblocksize){
 				dprint("%s\n", errstring[Esystem]);
-				panic("error writing block %llud: %llud bytes, written %llud: %r\n",
-						b->blkno, n, wn);
+				panic("error writing jumbo block %llud: %llud bytes, written %llud: %r\n",
+						startblkno, n, wn);
 			}
 			free(jumbo);
 			for(i = 0; i < n; i++){