567 lines · 9.7 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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); voidmain(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", 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);} voidforkserve(void){	serve(chan);} staticstruct{	int	nfilter;	Filter*	filters[100];}f; int alarmed; voidcatchalarm(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 */voidsyncproc(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;	}} voiddofilter(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;} voidstartproc(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);} voidconfinit(void){	conf.niobuf = 0;	conf.nuid = 600;	conf.nserve = 2;	conf.uidspace = conf.nuid*6;	conf.gidspace = conf.nuid*3;	cons.flags = 0;} static voiddochaninit(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;} intnetserve(char *netaddr){	int afd, lfd, fd;	char adir[2*NAMELEN], ldir[2*NAMELEN];	Chan *netchan; 	if(access("/net/tcp/clone", 0) < 0)		bind("#I", "/net", MAFTER);	if(access("/net.alt/tcp/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;		}	}} intsrvfd(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;} voidconsinit(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 */voidsyncall(void){	for(;;)		if(!syncblock())			return;} intaskream(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';} ulongmemsize(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 */intfsinit(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	 */

Lines 1–500 of 567.