code: mafs

ref: 84d66beb90246495861436c041297528298ba74f
dir: /ctl.c/

View raw version
#include "all.h"

enum { MAXARGS = 16 };

static int echo;

enum
{
	Cdf,
	Cchatty,
	Csync,
	Chalt,
	Cusers,
	Cecho,
	Cmax
};

int
cmdsync(Cmdbuf *)
{
	u64 n;

	while((n=sync()) > 0){
		// if(chatty9p > 1)
		dprint("shutdown: sync() finds %llud locked blocks\n", n);
		sleep(1000);
	}
	return 0;
}

int
cmdhalt(Cmdbuf *)
{
	shutdown();
	return Chalt;
}

int
cmdchatty(Cmdbuf *)
{
	extern int chatty9p;

	chatty9p = !chatty9p;
	return 0;
}

int
cmdnoauth(Cmdbuf *)
{
	noauth = 1;
	return 1;
}

int
cmdecho(Cmdbuf *cb)
{
	echo = strcmp(cb->f[1], "on") == 0;
	return 1;
}

int
cmdusers(Cmdbuf *)
{
	syncusers();
	return 0;
}

Cmdtab cmds[] = {
	{Cchatty, "chatty", 1},
	{Csync, "sync", 1},
	{Chalt, "halt", 0},
	{Cusers, "users", 1},
	{Cecho, "echo", 2},
};

int
runcmd(int idx, Cmdbuf *cb)
{
	switch(idx){
		case Cchatty:	return cmdchatty(cb); break;
		case Csync:	return cmdsync(cb); break;
		case Chalt:	return cmdhalt(cb); break;
		case Cusers:	return cmdusers(cb); break;
		case Cecho:	return cmdecho(cb); break;
		default:
			dprint("unknown idx %d\n", idx);
	}
	return idx;
};

void
ctlread(Req *req)
{
	u64 free, used;
	char buf[1024];
	int n;

	free = nfrees(&frees);
	used = config.nblocks - free;

/*	n = snprint(buf, 1024, "pending writes %llud blocks\n", pendingwrites());*/
	n = 0;
	if(config.size > TiB)
	n += snprint(buf+n, 1024-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
						"(MiB) free %ulld, used %ulld, total %ulld\n"
						"(GiB) free %ulld, used %ulld, total %ulld\n"
						"(TiB) free %ulld, used %ulld, total %ulld\n",
						free, used, config.nblocks,
						free * Blocksize / MiB,
						used * Blocksize / MiB,
						config.size / MiB,
						free * Blocksize / GiB,
						used * Blocksize / GiB,
						config.size / GiB,
						free * Blocksize / TiB,
						used * Blocksize / TiB,
						config.size / TiB
						);
	else if(config.size > GiB)
	n += snprint(buf+n, 1024-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
						"(MiB) free %ulld, used %ulld, total %ulld\n"
						"(GiB) free %ulld, used %ulld, total %ulld\n",
						free, used, config.nblocks,
						free * Blocksize / MiB,
						used * Blocksize / MiB,
						config.size / MiB,
						free * Blocksize / GiB,
						used * Blocksize / GiB,
						config.size / GiB
						);
	else if(config.size > MiB)
	n += snprint(buf+n, 1024-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
						"(MiB) free %ulld, used %ulld, total %ulld\n",
						free, used, config.nblocks,
						free * Blocksize / MiB,
						used * Blocksize / MiB,
						config.size / MiB
						);
	else
	n += snprint(buf+n, 1024-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
						"(KiB) free %ulld, used %ulld, total %ulld\n",
						free, used, config.nblocks,
						free * Blocksize / KiB,
						used * Blocksize / KiB,
						config.size / KiB
						);
	if(req->ifcall.offset < n){
		req->ofcall.count = min(req->ifcall.count,n);
		memcpy(req->ofcall.data, buf+req->ifcall.offset, req->ofcall.count);
		req->ofcall.offset = req->ifcall.offset+req->ofcall.count;
	}
	respond(req, nil);
}

u32 mpsrvpid = 0;
/* check the comments above shutdown() to understand */
void
ctlwrite(Req *req)
{
	Cmdbuf *cb;
	Cmdtab *ct;
	char srvfilename[Namelen];
	int n;

	if(chatty9p)
		dprint("consproc: >%s\n", req->ifcall.data);
	while((cb = parsecmd(req->ifcall.data, req->ifcall.count)) != nil){
		ct = lookupcmd(cb, cmds, nelem(cmds));
		if(ct != nil){
			req->ofcall.count = req->ifcall.count;
			req->ofcall.offset = req->ifcall.offset+req->ifcall.count;
			n = runcmd(ct->index, cb);
			respond(req, nil);
			if(ct->index == Chalt || n == Chalt){
				/* /srv/mafs_service file will not exist when mounted with -s */
				if(mpsrvpid &&
					snprint(srvfilename, Namelen, "/srv/%s", service) > 5){
					/*
						this stuff is only needed when the worker is doing
						the shutdown()
					 */
					remove(srvfilename);
					close(req->srv->infd);
					close(req->srv->outfd);
					if(mpsrvpid > 0){
						postnote(PNPROC, mpsrvpid, "halt");
						mpsrvpid = 0;
					}
				}else{
					close(1);
					close(0);
				}
				exits(nil);
			}
		}else{
			respond(req, errstring[Einval]);
		}
		free(cb);
	}
}

/* get rid of this after understanding what it does
static int
walkpath(Chan *ch, char *path, char **cr)
{
	char buf[Namelen], *p, *fp;

	fp = path;
	if(*path != '/'){
	noent:
		werrstr("%s: %s", fp, Enoent);
		return -1;
	}
	path++;
	for(;;){
		p = strchr(path, '/');
		if(p == nil){
			if(cr != nil){
				if(*path == 0){
					werrstr("%s: trailing slash", fp);
					return -1;
				}
				*cr = path;
				break;
			}
			p = path + strlen(path);
		}
		if(*path == '/'){
			path++;
			continue;
		}
		if(*path == 0)
			break;
		if(p - path >= Namelen)
			goto noent;
		memset(buf, 0, sizeof buf);
		memcpy(buf, path, p - path);
		if(chanwalk(ch, buf) <= 0){
			werrstr("%s: %r", fp);
			return -1;
		}
		if(*p == 0)
			break;
		path = p + 1;
	}
	return 1;
}

int
cmddebugdeind(int, char **argv)
{
	Chan *ch;
	Buf *b;
	Dentry *d;

	ch = chanattach(fsmain, 0);
	if(ch == nil)
		return -1;
	ch->uid = -1;
	if(walkpath(ch, argv[1], nil) < 0)
		goto error;
	rlock(fsmain);
	dprint("loc %ulld / %uld, offset %ulld\n", ch->loc->blk, ch->loc->deind, BLOCK * ch->loc->blk + (RBLOCK - BLOCK) + DENTRYSIZ * ch->loc->deind);
	b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
	if(b == nil){
		runlock(fsmain);
		goto error;
	}
	d = &b->de[ch->loc->deind];
	dprint("name %s\n", d->name);
	dprint("uid %d, muid %d, gid %d\n", d->uid, d->muid, d->gid);
	dprint("mode %#o, qid %ulld, type %#x, version %d\n", d->mode, d->path, d->type, d->vers);
	dprint("size %d\n", d->size);
	dprint("atime %ulld, mtime %ulld\n", d->atime, d->mtime);
	putbuf(b);
	runlock(fsmain);
	chanclunk(ch);
	return 0;
error:
	chanclunk(ch);
	return -1;
}

int
cmddebugchdeind(int, char **argv)
{
	Chan *ch;
	uchar *c;
	Buf *b;
	int loc, new;

	loc = strtol(argv[2], nil, 0);
	new = strtol(argv[3], nil, 0);
	if(loc >= DENTRYSIZ)
		return -9001;
	ch = chanattach(fsmain, 0);
	if(ch == nil)
		return -1;
	ch->uid = -1;
	if(walkpath(ch, argv[1], nil) < 0)
		goto error;
	rlock(fsmain);
	b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
	if(b == nil){
		runlock(fsmain);
		goto error;
	}
	c = (uchar *) &b->de[ch->loc->deind];
	dprint("loc %d, old value %#.2x, new value %#.2x\n", loc, c[loc], new);
	c[loc] = new;
	b->op |= BDELWRI;
	putbuf(b);
	runlock(fsmain);
	chanclunk(ch);
	return 0;
error:
	chanclunk(ch);
	return -1;
}

int
cmddebuggetblk(int argc, char **argv)
{
	Chan *ch;
	Buf *b;
	int rc;
	uvlong r, start, end, i;

	if(argc != 3 && argc != 4)
		return -9001;
	start = atoll(argv[2]);
	if(argc == 4)
		end = atoll(argv[3]);
	else
		end = start;
	ch = chanattach(fsmain, 0);
	if(ch == nil)
		return -1;
	ch->uid = -1;
	if(walkpath(ch, argv[1], nil) < 0)
		goto error;
	rlock(fsmain);
	b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
	if(b == nil){
		runlock(fsmain);
		goto error;
	}
	for(i = start; i <= end; i++){
		rc = getblk(fsmain, ch->loc, b, i, &r, GBREAD);
		if(rc > 0)
			dprint("getblk %ulld = %ulld\n", i, r);
		if(rc == 0)
			dprint("getblk %ulld not found\n", i);
		if(rc < 0)
			dprint("getblk %ulld: %r\n", i);
	}
	putbuf(b);
	runlock(fsmain);
	chanclunk(ch);
	return 0;
error:
	chanclunk(ch);
	return -1;
} */