code: mafs

ref: 80e6c118c65b013bde24f8b9c95881c0e3a73d3e
dir: /ctl.c/

View raw version
#include "all.h"

enum { MAXARGS = 16 };

extern Extents memunits;
static int echo;

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

int
cmdsync(Cmdbuf *)
{
	u64 n;

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

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

int
cmdchatty(Cmdbuf *)
{
	extern int chatty9p;

	chatty9p = !chatty9p;
	return 1;
}

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

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

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;
		default:
			dprint("unknown idx %d\n", idx);
	}
	return 0;
};

void
ctlread(Req *req)
{
	u64 nfree, used;
	char *buf;
	int n;

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

	buf = emalloc9p(MiB);
/*	n = snprint(buf, MiB, "pending writes %llud blocks\n", pendingwrites());*/
	n = snprint(buf, MiB, "hash buckets:\n");
	n += showhashbuckets(buf+n, MiB-n);
	n += snprint(buf+n, MiB-n, "memunits extents:\n");
	n += saveextents(&memunits, buf+n, MiB-n);
	n += snprint(buf+n, MiB-n, "frees extents:\n");
	n += saveextents(&frees, buf+n, MiB-n);
	if(config.size > TiB)
	n += snprint(buf+n, MiB-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",
						nfree, used, config.nblocks,
						nfree * Blocksize / MiB,
						used * Blocksize / MiB,
						config.size / MiB,
						nfree * Blocksize / GiB,
						used * Blocksize / GiB,
						config.size / GiB,
						nfree * Blocksize / TiB,
						used * Blocksize / TiB,
						config.size / TiB
						);
	else if(config.size > GiB)
	n += snprint(buf+n, MiB-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",
						nfree, used, config.nblocks,
						nfree * Blocksize / MiB,
						used * Blocksize / MiB,
						config.size / MiB,
						nfree * Blocksize / GiB,
						used * Blocksize / GiB,
						config.size / GiB
						);
	else if(config.size > MiB)
	n += snprint(buf+n, MiB-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
						"(MiB) free %ulld, used %ulld, total %ulld\n",
						nfree, used, config.nblocks,
						nfree * Blocksize / MiB,
						used * Blocksize / MiB,
						config.size / MiB
						);
	else
	n += snprint(buf+n, MiB-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
						"(KiB) free %ulld, used %ulld, total %ulld\n",
						nfree, used, config.nblocks,
						nfree * 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);
	free(buf);
}

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("ctlwrite %d -%s-\n", req->ifcall.count, req->ifcall.data);
	while((cb = parsecmd(req->ifcall.data, req->ifcall.count)) != nil &&
			cb->nf > 0){
		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);
			/* should respond based on n */
			// dprint("ct->index %d n %d\n", ct->index, n);
			if(n == 1)
				respond(req, nil);
			else
				respondcmderror(req, cb, "%r");
			if(ct->index == 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);
	}
}