code: mafs

ref: ce708f49bf5ec6c6b3fe1bb29d401c42b841b649
dir: /mafs.c/

View raw version
#include	"all.h"
#include	"pool.h"

char *devfile = nil;	/* device file path */
char service[Servicelen] = "\0";

/* use a byte for all these flags as hjfs? */
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);
Config config = {0};

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

void
main(int argc, char **argv)
{
	int doream, stdio;
	char buf[Servicelen];
	int pid, ctl;
	u64 nmemunits, size;
	Errenv env = {0};

	envpp = privalloc();
	*envpp = &env;
	if(waserror()){
		panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux",
			env.nlabel,
			env.label[0][JMPBUFPC], env.label[1][JMPBUFPC],
			env.label[2][JMPBUFPC], env.label[3][JMPBUFPC],
			env.label[4][JMPBUFPC], env.label[5][JMPBUFPC]);
	}

	/* mainmem->flags |= POOL_PARANOIA|POOL_LOGGING; */

	/*
	 * insulate from invoker's environment and keep it from swapping
	 */
	rfork(RFNAMEG|RFNOTEG|RFREND);

	nbuckets = 0;
	nmemunits = 0;
	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 'A':	noauth++; break;
	case 'D':	chatty9p++; break;
	case 'f':	/* devfile = ARGF(); */ break; /* to work with bootfs of /sys/src/9/boot/local.rc */
	case 'm':	nmemunits = atoll(EARGF(usage())); break;
	case 'r':
		doream = 1;
		/* fall through */
	case 'n':
		snprint(service, Servicelen, "%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);

	/*
		Minimum number of collisions = 3
		Minimum number of hash buckets = 7
		Minimum number of memunits = 7 * 3 * 2048 blocks = 43,008 blocks
	 */
	if(nmemunits < 42*KiB){
		nmemunits = size/Blocksize;
		if(nmemunits > 8*MiB)
			nmemunits = 8*MiB;
		else if(nmemunits < 42*KiB)
			nmemunits = 42*KiB;
	}
	nbuckets = nmemunits/(4*Ncollisions*Maxdatablockunits);
	if(nbuckets < 7)
		nbuckets = 7;

	if(chatty9p){
		dprint("\nPlan 9 %d-bit file server with %d-deep indirect blocks\n",
			sizeof(u64)*8, Niblock);
		dprint("nmemunits %llud nbuckets %llud\n",
				nmemunits, nbuckets);
	}

	formatinit();
	initmemunitpool(nmemunits);
	initextents(&frees, "blocks", 1, 0, 2, nil, dprintfd, panic, malloc9p);
	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, Servicelen, "%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;
}