ref: e82f565015fd0b75085d8d2a4f1aaca53e875f64
dir: /mafs.c/
#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; extern u64 npendingwrites; /* write throttling */ 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: mafs [-Ds] [-r service] [-n service] [-m nmemunits] [-h nbuckets] [-w npendingwrites] [-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; npendingwrites = 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 'w': npendingwrites = 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 */ if(nmemunits == 0) nmemunits = size/Rawblocksize > 8*MiB ? 8*MiB : size/Rawblocksize; if(nmemunits < KiB) nmemunits = KiB; if(npendingwrites == 0) npendingwrites = 2*nmemunits/3; 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 npendingwrites %llud nbuckets %llud\n", nmemunits, npendingwrites, nbuckets); } formatinit(); initmemunitpool(nmemunits); initextents(&frees); tlocks = emalloc9p(NTLOCK * sizeof *tlocks); initwriter(); 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)); }