ref: b3e875d7db45fca0cde9f4efa12872f61afc54d7
dir: /ctl.c/
#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; }; u32 fillctlmsg(s8 *buf, u32 nbuf) { u64 nfree, used; u64 n; nfree = nfrees(&frees); used = config.nblocks - nfree; n = snprint(buf, nbuf, "hash buckets:\n"); n += showhashbuckets(buf+n, nbuf-n); n += snprint(buf+n, nbuf-n, "memunits extents:\n"); n += saveextents(&memunits, buf+n, nbuf-n); n += snprint(buf+n, nbuf-n, "frees extents:\n"); n += saveextents(&frees, buf+n, nbuf-n); if(config.size > TiB) n += snprint(buf+n, nbuf-n, "(blocks) free %ulld, used %ulld, total %ulld\n" "(nbuf) 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 / nbuf, used * Blocksize / nbuf, config.size / nbuf, 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, nbuf-n, "(blocks) free %ulld, used %ulld, total %ulld\n" "(nbuf) free %ulld, used %ulld, total %ulld\n" "(GiB) free %ulld, used %ulld, total %ulld\n", nfree, used, config.nblocks, nfree * Blocksize / nbuf, used * Blocksize / nbuf, config.size / nbuf, nfree * Blocksize / GiB, used * Blocksize / GiB, config.size / GiB ); else if(config.size > nbuf) n += snprint(buf+n, nbuf-n, "(blocks) free %ulld, used %ulld, total %ulld\n" "(nbuf) free %ulld, used %ulld, total %ulld\n", nfree, used, config.nblocks, nfree * Blocksize / nbuf, used * Blocksize / nbuf, config.size / nbuf ); else n += snprint(buf+n, nbuf-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(n >= nbuf) panic("increase ctl message buffer: n %llud nbuf %ud\n", n, nbuf); return n; } void ctlread(Req *req) { Aux *aux; aux = (Aux*)req->fid->aux; if(aux->ctlmsg == nil){ aux->ctlmsg = emalloc9p(MiB); aux->nctlmsg = 0; } if(req->ifcall.offset == 0) aux->nctlmsg = fillctlmsg(aux->ctlmsg, MiB); if(req->ifcall.offset < aux->nctlmsg){ req->ofcall.count = min(req->ifcall.count,aux->nctlmsg-req->ifcall.offset); memcpy(req->ofcall.data, aux->ctlmsg+req->ifcall.offset, req->ofcall.count); req->ofcall.offset = req->ifcall.offset+req->ofcall.count; } if(req->ifcall.offset == aux->nctlmsg){ free(aux->ctlmsg); aux->ctlmsg = nil; aux->nctlmsg = 0; } respond(req, nil); } u32 mpsrvpid = 0; /* check the comments above shutdown() to understand */ void ctlwrite(Req *req) { Cmdbuf *cb; Cmdtab *ct; char srvfilename[Servicelen]; 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, Servicelen, "/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); } }