code: mafs

ref: b5d191e8cfa4fac05a02ea309df2541a2652ff23
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	*procname;

char *devfile = nil;	/* device file path */
char service[Namelen] = "\0";
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 */
int	wstatallow;
int	writegroup;
int	allownone;
static void	usage(void);
static void	printsizes(void);
Config config = {0};

static void
usage(void)
{
	fprint(2, "usage: mafs [-Ds] [-r service] [-n service] [-m nmemunits] [-h nbuckets] [-w npendingwrites] file\n");
	exits("usage");
}

void
main(int argc, char **argv)
{
	int doream, stdio;
	char buf[Namelen];
	int pid, ctl;
	u64 nmemunits, size;

	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 = 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;
	}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*Ntogether for jumbo writes when the writer
		queue is full
	 */
	if(nmemunits == 0)
		nmemunits = size/Rawblocksize > 8*MiB ? 8*MiB : size/Rawblocksize;
	if(nmemunits < KiB)
		nmemunits = KiB;
	if(npendingwrites == 0)
		npendingwrites = 2*(nmemunits-(4*Ntogether))/3;
	if(nbuckets == 0)
		nbuckets = (nmemunits-(4*Ntogether))/(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);
	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(stdio);
	/*
		we have started another proc to process /srv/service
		and it is my time to exit
	 */
	exits(nil);
}

/*
 * 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));
}