123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- #include "all.h"
- int sfd;
- int cmdmode = 0660;
- int rfd;
- int chat;
- extern char *wrenfile;
- extern int nwren;
- char *myname;
- int cmdfd;
- int writeallow; /* never on; for compatibility with fs */
- int wstatallow;
- int writegroup;
- int allownone;
- int noatime;
- int srvfd(char*, int, int);
- void usage(void);
- void confinit(void);
- Chan *chaninit(char*);
- void consinit(void);
- void forkserve(void);
- void
- main(int argc, char *argv[])
- {
- Filsys *fs;
- int ream, fsok;
- int newbufsize, nocheck;
- char buf[NAMELEN];
- int pid, ctl;
- progname = "kfs";
- procname = "init";
- /*
- * insulate from invoker's environment and keep it from swapping
- */
- rfork(RFNAMEG|RFNOTEG|RFREND);
- confinit();
- sfd = -1;
- ream = 0;
- newbufsize = 0;
- nocheck = 0;
- wrenfile = "/dev/sdC0/fs";
- pid = getpid();
- snprint(buf, sizeof buf, "/proc/%d/ctl", pid);
- ctl = open(buf, OWRITE);
- fprint(ctl, "noswap\n");
- close(ctl);
- buf[0] = '\0';
- ARGBEGIN{
- case 'b':
- newbufsize = atol(ARGF());
- break;
- case 'c':
- nocheck = 1;
- break;
- case 'f':
- wrenfile = ARGF();
- break;
- case 'm':
- nwren = atol(ARGF());
- break;
- case 'n':
- strncpy(buf, ARGF(), NAMELEN-1);
- buf[NAMELEN-1] = '\0';
- break;
- case 'p':
- cmdmode = atol(ARGF());
- break;
- case 'r':
- ream = 1;
- break;
- case 's':
- sfd = 0;
- rfd = dup(1, -1);
- close(1);
- if(open("/dev/cons", OWRITE) < 0)
- open("#c/cons", OWRITE);
- break;
- case 'B':
- conf.niobuf = strtoul(ARGF(), 0, 0);
- break;
- case 'C':
- chat = 1;
- break;
- default:
- usage();
- }ARGEND
- if(argc != 0)
- usage();
- cmdfd = 2;
- if (access(wrenfile, AREAD|AWRITE) == -1)
- sysfatal("%s cannot access device\n", wrenfile);
- formatinit();
- sublockinit();
- if(buf[0])
- sprint(service, "kfs.%s", buf);
- else
- strcpy(service, "kfs");
- chan = chaninit(service);
- consinit();
- tlocks = ialloc(NTLOCK * sizeof *tlocks);
- uid = ialloc(conf.nuid * sizeof(*uid));
- uidspace = ialloc(conf.uidspace * sizeof(*uidspace));
- gidspace = ialloc(conf.gidspace * sizeof(*gidspace));
- /*
- * init global locks
- */
- wlock(&mainlock); wunlock(&mainlock);
- /*
- * init the file system, ream it if needed, and get the block sizes
- */
- ream = fsinit(ream, newbufsize);
- iobufinit();
- for(fs=filesys; fs->name; fs++)
- if(fs->flags & FREAM){ /* set by fsinit if reamed */
- ream++;
- rootream(fs->dev, getraddr(fs->dev));
- superream(fs->dev, superaddr(fs->dev));
- }
- boottime = time(nil);
- consserve();
- fsok = superok(filesys[0].dev, superaddr(filesys[0].dev), 0);
- if(!nocheck && !ream && !fsok)
- cmd_exec("check fq");
- startproc(forkserve, "srv");
- startproc(syncproc, "sync");
- exits(0);
- }
- void
- forkserve(void)
- {
- serve(chan);
- }
- 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);
- }
- /*
- * process to synch blocks
- * it puts out a block/line every second
- * it waits 10 seconds if catches up.
- * in both cases, it takes about 10 seconds
- * to get up-to-date.
- *
- * it also updates the filter stats
- * and executes commands
- */
- void
- syncproc(void)
- {
- char buf[4*1024];
- Filter *ft;
- ulong c0, c1;
- long t, n, d;
- int i, p[2];
- /*
- * make a pipe for commands
- */
- if(pipe(p) < 0)
- panic("command pipe");
- sprint(buf, "#s/%s.cmd", service);
- srvfd(buf, cmdmode, p[0]);
- close(p[0]);
- cmdfd = p[1];
- notify(catchalarm);
- t = time(nil);
- for(;;){
- i = syncblock();
- alarmed = 0;
- alarm(i ? 1000: 10000);
- n = read(cmdfd, buf, sizeof buf - 1);
- if(n <= 0 && !alarmed)
- sleep(i ? 1000: 10000);
- alarm(0);
- if(n > 0){
- buf[n] = '\0';
- if(cmd_exec(buf))
- fprint(cmdfd, "done");
- else
- fprint(cmdfd, "unknown command");
- }
- n = time(nil);
- d = n - t;
- if(d < 0 || d > 5*60)
- d = 0;
- while(d >= 1) {
- d -= 1;
- for(i=0; i<f.nfilter; i++) {
- ft = f.filters[i];
- c0 = ft->count;
- c1 = c0 - ft->oldcount;
- ft->oldcount = c0;
- ft->filter[0] = famd(ft->filter[0], c1, 59, 60);
- ft->filter[1] = famd(ft->filter[1], c1, 599, 600);
- ft->filter[2] = famd(ft->filter[2], c1, 5999, 6000);
- }
- }
- t = n;
- }
- }
- void
- dofilter(Filter *ft)
- {
- int i;
- i = f.nfilter;
- if(i >= sizeof f.filters / sizeof f.filters[0]) {
- print("dofilter: too many filters\n");
- return;
- }
- f.filters[i] = ft;
- f.nfilter = i+1;
- }
- void
- startproc(void (*f)(void), char *name)
- {
- switch(rfork(RFMEM|RFFDG|RFPROC)){
- case -1:
- panic("can't fork");
- case 0:
- break;
- default:
- return;
- }
- procname = name;
- f();
- _exits(nil);
- }
- void
- confinit(void)
- {
- conf.niobuf = 0;
- conf.nuid = 600;
- conf.nserve = 2;
- conf.uidspace = conf.nuid*6;
- conf.gidspace = conf.nuid*3;
- cons.flags = 0;
- }
- static void
- dochaninit(Chan *cp, int fd)
- {
- cp->chan = fd;
- fileinit(cp);
- wlock(&cp->reflock);
- wunlock(&cp->reflock);
- lock(&cp->flock);
- unlock(&cp->flock);
- }
- Chan*
- chaninit(char *server)
- {
- Chan *cp;
- char buf[3*NAMELEN];
- int p[2];
- sprint(buf, "#s/%s", server);
- if(sfd < 0){
- if(pipe(p) < 0)
- panic("can't make a pipe");
- sfd = p[0];
- rfd = p[1];
- }
- srvfd(buf, 0666, sfd);
- close(sfd);
- cp = ialloc(sizeof *cp);
- cons.srvchan = cp;
- dochaninit(cp, rfd);
- return cp;
- }
- int
- netserve(char *netaddr)
- {
- int afd, lfd, fd;
- char adir[2*NAMELEN], ldir[2*NAMELEN];
- Chan *netchan;
- if(access("/net/il/clone", 0) < 0)
- bind("#I", "/net", MAFTER);
- if(access("/net.alt/il/clone", 0) < 0)
- bind("#I1", "/net.alt", MAFTER);
- afd = announce(netaddr, adir);
- if (afd < 0)
- return -1;
- switch (rfork(RFMEM|RFFDG|RFPROC)) {
- case -1:
- return -1;
- case 0:
- break;
- default:
- return 0;
- }
- for (;;) {
- lfd = listen(adir, ldir);
- if (lfd < 0)
- continue;
- fd = accept(lfd, ldir);
- if (fd < 0) {
- close(lfd);
- continue;
- }
- netchan = mallocz(sizeof(Chan), 1);
- if(netchan == nil)
- panic("out of memory");
- dochaninit(netchan, fd);
- switch (rfork(RFMEM|RFFDG|RFPROC)) {
- case -1:
- panic("can't fork");
- case 0:
- close(afd);
- close(lfd);
- serve(netchan);
- free(netchan);
- exits(0);
- default:
- close(fd);
- close(lfd);
- continue;
- }
- }
- }
- int
- srvfd(char *s, int mode, int sfd)
- {
- int fd;
- char buf[32];
- fd = create(s, ORCLOSE|OWRITE, mode);
- if(fd < 0){
- remove(s);
- fd = create(s, ORCLOSE|OWRITE, mode);
- if(fd < 0)
- panic(s);
- }
- sprint(buf, "%d", sfd);
- if(write(fd, buf, strlen(buf)) != strlen(buf))
- panic("srv write");
- return sfd;
- }
- void
- consinit(void)
- {
- int i;
- cons.chan = ialloc(sizeof(Chan));
- wlock(&cons.chan->reflock);
- wunlock(&cons.chan->reflock);
- lock(&cons.chan->flock);
- unlock(&cons.chan->flock);
- dofilter(&cons.work);
- dofilter(&cons.rate);
- dofilter(&cons.bhit);
- dofilter(&cons.bread);
- dofilter(&cons.binit);
- for(i = 0; i < MAXTAG; i++)
- dofilter(&cons.tags[i]);
- }
- /*
- * always called with mainlock locked
- */
- void
- syncall(void)
- {
- for(;;)
- if(!syncblock())
- return;
- }
- int
- askream(Filsys *fs)
- {
- char c;
- print("File system %s inconsistent\n", fs->name);
- print("Would you like to ream it (y/n)? ");
- read(0, &c, 1);
- return c == 'y';
- }
- ulong
- 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;
- }
- /*
- * init the devices
- * wipe some of the file systems, or all if ream is set
- * this code really assumes that only one file system exists
- */
- int
- fsinit(int ream, int newbufsize)
- {
- Filsys *fs;
- RBUFSIZE = 4 * 1024;
- for(fs=filesys; fs->name; fs++)
- (*devcall[fs->dev.type].init)(fs->dev);
- if(newbufsize == 0)
- newbufsize = RBUFSIZE;
- if(conf.niobuf == 0) {
- conf.niobuf = memsize()/10;
- if(conf.niobuf > 2*1024*1024)
- conf.niobuf = 2*1024*1024;
- conf.niobuf /= newbufsize;
- if(conf.niobuf < 30)
- conf.niobuf = 30;
- }
- BUFSIZE = RBUFSIZE - sizeof(Tag);
- for(fs=filesys; fs->name; fs++)
- if(ream || (*devcall[fs->dev.type].check)(fs->dev) && askream(fs)){
- RBUFSIZE = newbufsize;
- BUFSIZE = RBUFSIZE - sizeof(Tag);
- (*devcall[fs->dev.type].ream)(fs->dev);
- fs->flags |= FREAM;
- ream = 1;
- }
- /*
- * set up the block size dependant variables
- */
- BUFSIZE = RBUFSIZE - sizeof(Tag);
- DIRPERBUF = BUFSIZE / sizeof(Dentry);
- INDPERBUF = BUFSIZE / sizeof(long);
- INDPERBUF2 = INDPERBUF * INDPERBUF;
- FEPERBUF = (BUFSIZE - sizeof(Super1) - sizeof(long)) / sizeof(long);
- return ream;
- }
- /*
- * allocate rest of mem
- * for io buffers.
- */
- #define HWIDTH 5 /* buffers per hash */
- void
- iobufinit(void)
- {
- long i;
- Iobuf *p, *q;
- Hiob *hp;
- i = conf.niobuf*RBUFSIZE;
- niob = i / (sizeof(Iobuf) + RBUFSIZE + sizeof(Hiob)/HWIDTH);
- nhiob = niob / HWIDTH;
- while(!prime(nhiob))
- nhiob++;
- if(chat)
- print(" %ld buffers; %ld hashes\n", niob, nhiob);
- hiob = ialloc(nhiob * sizeof(Hiob));
- hp = hiob;
- for(i=0; i<nhiob; i++) {
- lock(hp);
- unlock(hp);
- hp++;
- }
- p = ialloc(niob * sizeof(Iobuf));
- hp = hiob;
- for(i=0; i<niob; i++) {
- qlock(p);
- qunlock(p);
- if(hp == hiob)
- hp = hiob + nhiob;
- hp--;
- q = hp->link;
- if(q) {
- p->fore = q;
- p->back = q->back;
- q->back = p;
- p->back->fore = p;
- } else {
- hp->link = p;
- p->fore = p;
- p->back = p;
- }
- p->dev = devnone;
- p->addr = -1;
- p->xiobuf = ialloc(RBUFSIZE);
- p->iobuf = (char*)-1;
- p++;
- }
- }
- void
- usage(void)
- {
- fprint(2, "usage: kfs [-cCr] [-b bufsize] [-s infd outfd] [-f fsfile]\n");
- exits(0);
- }
|