code: mafs

ref: a566629485f872d51d4d5661d8b4aa32bd45f3e2
dir: /mafs.c/

View raw version
#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;

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] [-h nbuckets] [-a announce-string]... fsfile\n");
	exits("usage");
}

void
main(int argc, char **argv)
{
	static char *nets[8];
	int doream, stdio, netc;
	char buf[Namelen];
	int pid, ctl;

	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 = Nbuckets;
	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 = atoi(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(chatty9p){
		dprint("\nPlan 9 %d-bit file server with %d-deep indirect blocks\n",
			sizeof(u64)*8, Niblock);
		printsizes();
	}

	if (access(devfile, AREAD|AWRITE) == -1)
		sysfatal("%s cannot access device", devfile);

	formatinit();

	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);
	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 = Ndspanid, 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 spans, max;

	dprint("Namelen %d Ndspanid %d Niblock %d\n", Namelen, Ndspanid, Niblock);
	dprint("Blocksize %d Nspanidperblock %d Nindperblock %d\n",
			Blocksize, Nspanidperblock, Nindperblock);
	dprint("Maxspanlen %llud Maxspansize %llud\n",
			Maxspanlen, Maxspansize);

	spans = nperindunit(Tind0);
	dprint("A %s unit points to %lld data spans (%llud bytes)\n",
			 tagnames[Tind0], spans, spans*Maxspansize);
	dprint("	block points to %lld data spans\n", nperiblock(Tind0));
	for (i = Tind1; i < Maxtind; i++) {
		spans = nperindunit(i);
		dprint("A %s unit points to %lld data spans (%llud bytes)\n",
			 tagnames[i], spans, spans*Maxspansize);
		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*Maxspansize = %llud bytes = %llud TB)\n",
			max, max*Maxspansize, (max*Maxspansize)/(MB*MB));
}