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++){