13e12c5d1SDavid du Colombier /* 23e12c5d1SDavid du Colombier * iostats - Gather file system information 33e12c5d1SDavid du Colombier */ 43e12c5d1SDavid du Colombier #include <u.h> 53e12c5d1SDavid du Colombier #include <libc.h> 6219b2ee8SDavid du Colombier #include <auth.h> 73e12c5d1SDavid du Colombier #include <fcall.h> 83e12c5d1SDavid du Colombier #define Extern 93e12c5d1SDavid du Colombier #include "statfs.h" 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier void runprog(char**); 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier void (*fcalls[])(Fsrpc*) = 143e12c5d1SDavid du Colombier { 159a747e4fSDavid du Colombier [Tversion] Xversion, 169a747e4fSDavid du Colombier [Tauth] Xauth, 173e12c5d1SDavid du Colombier [Tflush] Xflush, 183e12c5d1SDavid du Colombier [Tattach] Xattach, 193e12c5d1SDavid du Colombier [Twalk] Xwalk, 203e12c5d1SDavid du Colombier [Topen] slave, 213e12c5d1SDavid du Colombier [Tcreate] Xcreate, 223e12c5d1SDavid du Colombier [Tclunk] Xclunk, 233e12c5d1SDavid du Colombier [Tread] slave, 243e12c5d1SDavid du Colombier [Twrite] slave, 253e12c5d1SDavid du Colombier [Tremove] Xremove, 263e12c5d1SDavid du Colombier [Tstat] Xstat, 273e12c5d1SDavid du Colombier [Twstat] Xwstat, 283e12c5d1SDavid du Colombier }; 293e12c5d1SDavid du Colombier 303e12c5d1SDavid du Colombier int p[2]; 313e12c5d1SDavid du Colombier 323e12c5d1SDavid du Colombier void 337dd7cddfSDavid du Colombier usage(void) 347dd7cddfSDavid du Colombier { 357dd7cddfSDavid du Colombier fprint(2, "usage: iostats [-d] [-f debugfile] cmds [args ...]\n"); 367dd7cddfSDavid du Colombier exits("usage"); 377dd7cddfSDavid du Colombier } 387dd7cddfSDavid du Colombier 397dd7cddfSDavid du Colombier void 403e12c5d1SDavid du Colombier main(int argc, char **argv) 413e12c5d1SDavid du Colombier { 423e12c5d1SDavid du Colombier Fsrpc *r; 433e12c5d1SDavid du Colombier Rpc *rpc; 443e12c5d1SDavid du Colombier Proc *m; 453e12c5d1SDavid du Colombier Frec *fr; 463e12c5d1SDavid du Colombier Fid *fid; 473e12c5d1SDavid du Colombier ulong ttime; 483e12c5d1SDavid du Colombier char *dbfile, *s; 497dd7cddfSDavid du Colombier char buf[128]; 503e12c5d1SDavid du Colombier float brpsec, bwpsec, bppsec; 517dd7cddfSDavid du Colombier int type, cpid, fspid, n; 523e12c5d1SDavid du Colombier 533e12c5d1SDavid du Colombier dbfile = DEBUGFILE; 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier ARGBEGIN{ 563e12c5d1SDavid du Colombier case 'd': 573e12c5d1SDavid du Colombier dbg++; 583e12c5d1SDavid du Colombier break; 593e12c5d1SDavid du Colombier case 'f': 603e12c5d1SDavid du Colombier dbfile = ARGF(); 613e12c5d1SDavid du Colombier break; 623e12c5d1SDavid du Colombier default: 637dd7cddfSDavid du Colombier usage(); 643e12c5d1SDavid du Colombier }ARGEND 653e12c5d1SDavid du Colombier 663e12c5d1SDavid du Colombier if(argc == 0) 677dd7cddfSDavid du Colombier usage(); 683e12c5d1SDavid du Colombier 693e12c5d1SDavid du Colombier if(dbg) { 703e12c5d1SDavid du Colombier close(2); 719a747e4fSDavid du Colombier create(dbfile, OWRITE, 0666); 723e12c5d1SDavid du Colombier } 733e12c5d1SDavid du Colombier 743e12c5d1SDavid du Colombier if(pipe(p) < 0) 753e12c5d1SDavid du Colombier fatal("pipe"); 763e12c5d1SDavid du Colombier 773e12c5d1SDavid du Colombier switch(cpid = fork()) { 783e12c5d1SDavid du Colombier case -1: 793e12c5d1SDavid du Colombier fatal("fork"); 803e12c5d1SDavid du Colombier case 0: 813e12c5d1SDavid du Colombier close(p[1]); 823e12c5d1SDavid du Colombier if(getwd(buf, sizeof(buf)) == 0) 833e12c5d1SDavid du Colombier fatal("no working directory"); 843e12c5d1SDavid du Colombier 853e12c5d1SDavid du Colombier rfork(RFENVG|RFNAMEG|RFNOTEG); 869a747e4fSDavid du Colombier if(mount(p[0], -1, "/", MREPL, "") < 0) 873e12c5d1SDavid du Colombier fatal("mount /"); 883e12c5d1SDavid du Colombier 893e12c5d1SDavid du Colombier bind("#c/pid", "/dev/pid", MREPL); 907dd7cddfSDavid du Colombier bind("#e", "/env", MREPL|MCREATE); 913e12c5d1SDavid du Colombier close(0); 923e12c5d1SDavid du Colombier close(1); 933e12c5d1SDavid du Colombier close(2); 943e12c5d1SDavid du Colombier open("/fd/0", OREAD); 953e12c5d1SDavid du Colombier open("/fd/1", OWRITE); 963e12c5d1SDavid du Colombier open("/fd/2", OWRITE); 973e12c5d1SDavid du Colombier 983e12c5d1SDavid du Colombier if(chdir(buf) < 0) 993e12c5d1SDavid du Colombier fatal("chdir"); 1003e12c5d1SDavid du Colombier 1013e12c5d1SDavid du Colombier runprog(argv); 1023e12c5d1SDavid du Colombier default: 1033e12c5d1SDavid du Colombier close(p[0]); 1043e12c5d1SDavid du Colombier } 1053e12c5d1SDavid du Colombier 1063e12c5d1SDavid du Colombier switch(fspid = fork()) { 1073e12c5d1SDavid du Colombier default: 1089a747e4fSDavid du Colombier while(cpid != waitpid()) 1093e12c5d1SDavid du Colombier ; 110219b2ee8SDavid du Colombier postnote(PNPROC, fspid, DONESTR); 1119a747e4fSDavid du Colombier while(fspid != waitpid()) 1123e12c5d1SDavid du Colombier ; 1133e12c5d1SDavid du Colombier exits(0); 1143e12c5d1SDavid du Colombier case -1: 1153e12c5d1SDavid du Colombier fatal("fork"); 1163e12c5d1SDavid du Colombier case 0: 1173e12c5d1SDavid du Colombier break; 1183e12c5d1SDavid du Colombier } 1193e12c5d1SDavid du Colombier 1203e12c5d1SDavid du Colombier /* Allocate work queues in shared memory */ 1213e12c5d1SDavid du Colombier malloc(Dsegpad); 1223e12c5d1SDavid du Colombier Workq = malloc(sizeof(Fsrpc)*Nr_workbufs); 1233e12c5d1SDavid du Colombier stats = malloc(sizeof(Stats)); 1247dd7cddfSDavid du Colombier fhash = mallocz(sizeof(Fid*)*FHASHSIZE, 1); 1253e12c5d1SDavid du Colombier 1263e12c5d1SDavid du Colombier if(Workq == 0 || fhash == 0 || stats == 0) 1273e12c5d1SDavid du Colombier fatal("no initial memory"); 1283e12c5d1SDavid du Colombier 1293e12c5d1SDavid du Colombier memset(Workq, 0, sizeof(Fsrpc)*Nr_workbufs); 1303e12c5d1SDavid du Colombier memset(stats, 0, sizeof(Stats)); 1313e12c5d1SDavid du Colombier 1329a747e4fSDavid du Colombier stats->rpc[Tversion].name = "version"; 1339a747e4fSDavid du Colombier stats->rpc[Tauth].name = "auth"; 1343e12c5d1SDavid du Colombier stats->rpc[Tflush].name = "flush"; 1353e12c5d1SDavid du Colombier stats->rpc[Tattach].name = "attach"; 1363e12c5d1SDavid du Colombier stats->rpc[Twalk].name = "walk"; 1373e12c5d1SDavid du Colombier stats->rpc[Topen].name = "open"; 1383e12c5d1SDavid du Colombier stats->rpc[Tcreate].name = "create"; 1393e12c5d1SDavid du Colombier stats->rpc[Tclunk].name = "clunk"; 1403e12c5d1SDavid du Colombier stats->rpc[Tread].name = "read"; 1413e12c5d1SDavid du Colombier stats->rpc[Twrite].name = "write"; 1423e12c5d1SDavid du Colombier stats->rpc[Tremove].name = "remove"; 1433e12c5d1SDavid du Colombier stats->rpc[Tstat].name = "stat"; 1443e12c5d1SDavid du Colombier stats->rpc[Twstat].name = "wstat"; 1453e12c5d1SDavid du Colombier 1469a747e4fSDavid du Colombier for(n = 0; n < Maxrpc; n++) 147*ab3dc52fSDavid du Colombier stats->rpc[n].lo = 10000000000LL; 1483e12c5d1SDavid du Colombier 1499a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 1503e12c5d1SDavid du Colombier 1513e12c5d1SDavid du Colombier if(chdir("/") < 0) 1523e12c5d1SDavid du Colombier fatal("chdir"); 1533e12c5d1SDavid du Colombier 1543e12c5d1SDavid du Colombier initroot(); 1553e12c5d1SDavid du Colombier 1563e12c5d1SDavid du Colombier DEBUG(2, "statfs: %s\n", buf); 1573e12c5d1SDavid du Colombier 1583e12c5d1SDavid du Colombier notify(catcher); 1593e12c5d1SDavid du Colombier 1603e12c5d1SDavid du Colombier for(;;) { 1613e12c5d1SDavid du Colombier r = getsbuf(); 1623e12c5d1SDavid du Colombier if(r == 0) 1633e12c5d1SDavid du Colombier fatal("Out of service buffers"); 1643e12c5d1SDavid du Colombier 1659a747e4fSDavid du Colombier n = read9pmsg(p[1], r->buf, sizeof(r->buf)); 1663e12c5d1SDavid du Colombier if(done) 1673e12c5d1SDavid du Colombier break; 1683e12c5d1SDavid du Colombier if(n < 0) 1693e12c5d1SDavid du Colombier fatal("read server"); 1703e12c5d1SDavid du Colombier 1719a747e4fSDavid du Colombier if(convM2S(r->buf, n, &r->work) == 0) 1723e12c5d1SDavid du Colombier fatal("format error"); 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier stats->nrpc++; 1753e12c5d1SDavid du Colombier stats->nproto += n; 1763e12c5d1SDavid du Colombier 1773e12c5d1SDavid du Colombier if(r->work.fid < 0) 1783e12c5d1SDavid du Colombier fatal("fid out of range"); 1793e12c5d1SDavid du Colombier 1807dd7cddfSDavid du Colombier DEBUG(2, "%F\n", &r->work); 1813e12c5d1SDavid du Colombier 1823e12c5d1SDavid du Colombier type = r->work.type; 1833e12c5d1SDavid du Colombier rpc = &stats->rpc[type]; 1843e12c5d1SDavid du Colombier rpc->count++; 1853e12c5d1SDavid du Colombier rpc->bin += n; 1863e12c5d1SDavid du Colombier (fcalls[type])(r); 1873e12c5d1SDavid du Colombier } 1883e12c5d1SDavid du Colombier 1893e12c5d1SDavid du Colombier /* Clear away the slave children */ 1903e12c5d1SDavid du Colombier for(m = Proclist; m; m = m->next) 191219b2ee8SDavid du Colombier postnote(PNPROC, m->pid, "kill"); 1923e12c5d1SDavid du Colombier 1933e12c5d1SDavid du Colombier rpc = &stats->rpc[Tread]; 194*ab3dc52fSDavid du Colombier brpsec = (float)stats->totread / (((float)rpc->time/1e9)+.000001); 1953e12c5d1SDavid du Colombier 1963e12c5d1SDavid du Colombier rpc = &stats->rpc[Twrite]; 197*ab3dc52fSDavid du Colombier bwpsec = (float)stats->totwrite / (((float)rpc->time/1e9)+.000001); 1983e12c5d1SDavid du Colombier 1993e12c5d1SDavid du Colombier ttime = 0; 2009a747e4fSDavid du Colombier for(n = 0; n < Maxrpc; n++) { 2013e12c5d1SDavid du Colombier rpc = &stats->rpc[n]; 2023e12c5d1SDavid du Colombier if(rpc->count == 0) 2033e12c5d1SDavid du Colombier continue; 2043e12c5d1SDavid du Colombier ttime += rpc->time; 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier 207*ab3dc52fSDavid du Colombier bppsec = (float)stats->nproto / ((ttime/1e9)+.000001); 2083e12c5d1SDavid du Colombier 2097dd7cddfSDavid du Colombier fprint(2, "\nread %lud bytes, %g Kb/sec\n", stats->totread, brpsec/1024.0); 2107dd7cddfSDavid du Colombier fprint(2, "write %lud bytes, %g Kb/sec\n", stats->totwrite, bwpsec/1024.0); 2117dd7cddfSDavid du Colombier fprint(2, "protocol %lud bytes, %g Kb/sec\n", stats->nproto, bppsec/1024.0); 2127dd7cddfSDavid du Colombier fprint(2, "rpc %lud count\n\n", stats->nrpc); 2133e12c5d1SDavid du Colombier 214*ab3dc52fSDavid du Colombier fprint(2, "%-10s %5s %5s %5s %5s %5s T R\n", 2153e12c5d1SDavid du Colombier "Message", "Count", "Low", "High", "Time", "Averg"); 2163e12c5d1SDavid du Colombier 2179a747e4fSDavid du Colombier for(n = 0; n < Maxrpc; n++) { 2183e12c5d1SDavid du Colombier rpc = &stats->rpc[n]; 2193e12c5d1SDavid du Colombier if(rpc->count == 0) 2203e12c5d1SDavid du Colombier continue; 221*ab3dc52fSDavid du Colombier fprint(2, "%-10s %5lud %5llud %5llud %5llud %5llud ms %8lud %8lud bytes\n", 2223e12c5d1SDavid du Colombier rpc->name, 2233e12c5d1SDavid du Colombier rpc->count, 224*ab3dc52fSDavid du Colombier rpc->lo/1000000, 225*ab3dc52fSDavid du Colombier rpc->hi/1000000, 226*ab3dc52fSDavid du Colombier rpc->time/1000000, 227*ab3dc52fSDavid du Colombier rpc->time/1000000/rpc->count, 2283e12c5d1SDavid du Colombier rpc->bin, 2293e12c5d1SDavid du Colombier rpc->bout); 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier for(n = 0; n < FHASHSIZE; n++) 2333e12c5d1SDavid du Colombier for(fid = fhash[n]; fid; fid = fid->next) 2343e12c5d1SDavid du Colombier if(fid->nread || fid->nwrite) 2353e12c5d1SDavid du Colombier fidreport(fid); 2363e12c5d1SDavid du Colombier if(frhead == 0) 2373e12c5d1SDavid du Colombier exits(0); 2383e12c5d1SDavid du Colombier 2393e12c5d1SDavid du Colombier fprint(2, "\nOpens Reads (bytes) Writes (bytes) File\n"); 2403e12c5d1SDavid du Colombier for(fr = frhead; fr; fr = fr->next) { 2413e12c5d1SDavid du Colombier s = fr->op; 2423e12c5d1SDavid du Colombier if(*s) { 2433e12c5d1SDavid du Colombier if(strcmp(s, "/fd/0") == 0) 2443e12c5d1SDavid du Colombier s = "(stdin)"; 2453e12c5d1SDavid du Colombier else 2463e12c5d1SDavid du Colombier if(strcmp(s, "/fd/1") == 0) 2473e12c5d1SDavid du Colombier s = "(stdout)"; 2483e12c5d1SDavid du Colombier else 2493e12c5d1SDavid du Colombier if(strcmp(s, "/fd/2") == 0) 2503e12c5d1SDavid du Colombier s = "(stderr)"; 2513e12c5d1SDavid du Colombier } 2523e12c5d1SDavid du Colombier else 2533e12c5d1SDavid du Colombier s = "/."; 2543e12c5d1SDavid du Colombier 2557dd7cddfSDavid du Colombier fprint(2, "%5lud %8lud %8lud %8lud %8lud %s\n", fr->opens, fr->nread, fr->bread, 2563e12c5d1SDavid du Colombier fr->nwrite, fr->bwrite, s); 2573e12c5d1SDavid du Colombier } 2583e12c5d1SDavid du Colombier 2593e12c5d1SDavid du Colombier exits(0); 2603e12c5d1SDavid du Colombier } 2613e12c5d1SDavid du Colombier 2623e12c5d1SDavid du Colombier void 2633e12c5d1SDavid du Colombier reply(Fcall *r, Fcall *t, char *err) 2643e12c5d1SDavid du Colombier { 2659a747e4fSDavid du Colombier uchar data[IOHDRSZ+Maxfdata]; 2663e12c5d1SDavid du Colombier int n; 2673e12c5d1SDavid du Colombier 2683e12c5d1SDavid du Colombier t->tag = r->tag; 2693e12c5d1SDavid du Colombier t->fid = r->fid; 2703e12c5d1SDavid du Colombier if(err) { 2713e12c5d1SDavid du Colombier t->type = Rerror; 2729a747e4fSDavid du Colombier t->ename = err; 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier else 2753e12c5d1SDavid du Colombier t->type = r->type + 1; 2763e12c5d1SDavid du Colombier 2773e12c5d1SDavid du Colombier DEBUG(2, "\t%F\n", t); 2783e12c5d1SDavid du Colombier 2799a747e4fSDavid du Colombier n = convS2M(t, data, sizeof data); 2803e12c5d1SDavid du Colombier if(write(p[1], data, n)!=n) 2813e12c5d1SDavid du Colombier fatal("mount write"); 2823e12c5d1SDavid du Colombier stats->nproto += n; 2833e12c5d1SDavid du Colombier stats->rpc[t->type-1].bout += n; 2843e12c5d1SDavid du Colombier } 2853e12c5d1SDavid du Colombier 2863e12c5d1SDavid du Colombier Fid * 2873e12c5d1SDavid du Colombier getfid(int nr) 2883e12c5d1SDavid du Colombier { 2893e12c5d1SDavid du Colombier Fid *f; 2903e12c5d1SDavid du Colombier 2913e12c5d1SDavid du Colombier for(f = fidhash(nr); f; f = f->next) 2923e12c5d1SDavid du Colombier if(f->nr == nr) 2933e12c5d1SDavid du Colombier return f; 2943e12c5d1SDavid du Colombier 2953e12c5d1SDavid du Colombier return 0; 2963e12c5d1SDavid du Colombier } 2973e12c5d1SDavid du Colombier 2983e12c5d1SDavid du Colombier int 2993e12c5d1SDavid du Colombier freefid(int nr) 3003e12c5d1SDavid du Colombier { 3013e12c5d1SDavid du Colombier Fid *f, **l; 3023e12c5d1SDavid du Colombier 3033e12c5d1SDavid du Colombier l = &fidhash(nr); 3043e12c5d1SDavid du Colombier for(f = *l; f; f = f->next) { 3053e12c5d1SDavid du Colombier if(f->nr == nr) { 3063e12c5d1SDavid du Colombier *l = f->next; 3073e12c5d1SDavid du Colombier f->next = fidfree; 3083e12c5d1SDavid du Colombier fidfree = f; 3093e12c5d1SDavid du Colombier return 1; 3103e12c5d1SDavid du Colombier } 3113e12c5d1SDavid du Colombier l = &f->next; 3123e12c5d1SDavid du Colombier } 3133e12c5d1SDavid du Colombier 3143e12c5d1SDavid du Colombier return 0; 3153e12c5d1SDavid du Colombier } 3163e12c5d1SDavid du Colombier 3173e12c5d1SDavid du Colombier Fid * 3183e12c5d1SDavid du Colombier newfid(int nr) 3193e12c5d1SDavid du Colombier { 3203e12c5d1SDavid du Colombier Fid *new, **l; 3213e12c5d1SDavid du Colombier int i; 3223e12c5d1SDavid du Colombier 3233e12c5d1SDavid du Colombier l = &fidhash(nr); 3243e12c5d1SDavid du Colombier for(new = *l; new; new = new->next) 3253e12c5d1SDavid du Colombier if(new->nr == nr) 3263e12c5d1SDavid du Colombier return 0; 3273e12c5d1SDavid du Colombier 3283e12c5d1SDavid du Colombier if(fidfree == 0) { 3297dd7cddfSDavid du Colombier fidfree = mallocz(sizeof(Fid) * Fidchunk, 1); 3303e12c5d1SDavid du Colombier if(fidfree == 0) 3313e12c5d1SDavid du Colombier fatal("out of memory"); 3323e12c5d1SDavid du Colombier 3333e12c5d1SDavid du Colombier for(i = 0; i < Fidchunk-1; i++) 3343e12c5d1SDavid du Colombier fidfree[i].next = &fidfree[i+1]; 3353e12c5d1SDavid du Colombier 3363e12c5d1SDavid du Colombier fidfree[Fidchunk-1].next = 0; 3373e12c5d1SDavid du Colombier } 3383e12c5d1SDavid du Colombier 3393e12c5d1SDavid du Colombier new = fidfree; 3403e12c5d1SDavid du Colombier fidfree = new->next; 3413e12c5d1SDavid du Colombier 3423e12c5d1SDavid du Colombier memset(new, 0, sizeof(Fid)); 3433e12c5d1SDavid du Colombier new->next = *l; 3443e12c5d1SDavid du Colombier *l = new; 3453e12c5d1SDavid du Colombier new->nr = nr; 3463e12c5d1SDavid du Colombier new->fid = -1; 3473e12c5d1SDavid du Colombier new->nread = 0; 3483e12c5d1SDavid du Colombier new->nwrite = 0; 3493e12c5d1SDavid du Colombier new->bread = 0; 3503e12c5d1SDavid du Colombier new->bwrite = 0; 3513e12c5d1SDavid du Colombier 3523e12c5d1SDavid du Colombier return new; 3533e12c5d1SDavid du Colombier } 3543e12c5d1SDavid du Colombier 3553e12c5d1SDavid du Colombier Fsrpc * 3563e12c5d1SDavid du Colombier getsbuf(void) 3573e12c5d1SDavid du Colombier { 3583e12c5d1SDavid du Colombier static int ap; 3593e12c5d1SDavid du Colombier int look; 3603e12c5d1SDavid du Colombier Fsrpc *wb; 3613e12c5d1SDavid du Colombier 3623e12c5d1SDavid du Colombier for(look = 0; look < Nr_workbufs; look++) { 3633e12c5d1SDavid du Colombier if(++ap == Nr_workbufs) 3643e12c5d1SDavid du Colombier ap = 0; 3653e12c5d1SDavid du Colombier if(Workq[ap].busy == 0) 3663e12c5d1SDavid du Colombier break; 3673e12c5d1SDavid du Colombier } 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier if(look == Nr_workbufs) 3703e12c5d1SDavid du Colombier fatal("No more work buffers"); 3713e12c5d1SDavid du Colombier 3723e12c5d1SDavid du Colombier wb = &Workq[ap]; 3733e12c5d1SDavid du Colombier wb->pid = 0; 3743e12c5d1SDavid du Colombier wb->canint = 0; 3753e12c5d1SDavid du Colombier wb->flushtag = NOTAG; 3763e12c5d1SDavid du Colombier wb->busy = 1; 3773e12c5d1SDavid du Colombier 3783e12c5d1SDavid du Colombier return wb; 3793e12c5d1SDavid du Colombier } 3803e12c5d1SDavid du Colombier 3813e12c5d1SDavid du Colombier char * 3823e12c5d1SDavid du Colombier strcatalloc(char *p, char *n) 3833e12c5d1SDavid du Colombier { 3843e12c5d1SDavid du Colombier char *v; 3853e12c5d1SDavid du Colombier 3863e12c5d1SDavid du Colombier v = realloc(p, strlen(p)+strlen(n)+1); 3873e12c5d1SDavid du Colombier if(v == 0) 3883e12c5d1SDavid du Colombier fatal("no memory"); 3893e12c5d1SDavid du Colombier strcat(v, n); 3903e12c5d1SDavid du Colombier return v; 3913e12c5d1SDavid du Colombier } 3923e12c5d1SDavid du Colombier 3933e12c5d1SDavid du Colombier File * 3943e12c5d1SDavid du Colombier file(File *parent, char *name) 3953e12c5d1SDavid du Colombier { 3963e12c5d1SDavid du Colombier char buf[128]; 3973e12c5d1SDavid du Colombier File *f, *new; 3989a747e4fSDavid du Colombier Dir *dir; 3993e12c5d1SDavid du Colombier 4007dd7cddfSDavid du Colombier DEBUG(2, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); 4013e12c5d1SDavid du Colombier 4023e12c5d1SDavid du Colombier for(f = parent->child; f; f = f->childlist) 4033e12c5d1SDavid du Colombier if(strcmp(name, f->name) == 0) 4047dd7cddfSDavid du Colombier break; 4053e12c5d1SDavid du Colombier 4067dd7cddfSDavid du Colombier if(f != nil && !f->inval) 4077dd7cddfSDavid du Colombier return f; 4083e12c5d1SDavid du Colombier makepath(buf, parent, name); 4099a747e4fSDavid du Colombier dir = dirstat(buf); 4109a747e4fSDavid du Colombier if(dir == nil) 4113e12c5d1SDavid du Colombier return 0; 4127dd7cddfSDavid du Colombier if(f != nil){ 4139a747e4fSDavid du Colombier free(dir); 4147dd7cddfSDavid du Colombier f->inval = 0; 4157dd7cddfSDavid du Colombier return f; 4167dd7cddfSDavid du Colombier } 4173e12c5d1SDavid du Colombier 4183e12c5d1SDavid du Colombier new = malloc(sizeof(File)); 4193e12c5d1SDavid du Colombier if(new == 0) 4203e12c5d1SDavid du Colombier fatal("no memory"); 4213e12c5d1SDavid du Colombier 4223e12c5d1SDavid du Colombier memset(new, 0, sizeof(File)); 4239a747e4fSDavid du Colombier new->name = strdup(name); 4249a747e4fSDavid du Colombier if(new->name == nil) 4259a747e4fSDavid du Colombier fatal("can't strdup"); 4269a747e4fSDavid du Colombier new->qid.type = dir->qid.type; 4279a747e4fSDavid du Colombier new->qid.vers = dir->qid.vers; 4289a747e4fSDavid du Colombier new->qid.path = ++qid; 4293e12c5d1SDavid du Colombier 4303e12c5d1SDavid du Colombier new->parent = parent; 4313e12c5d1SDavid du Colombier new->childlist = parent->child; 4323e12c5d1SDavid du Colombier parent->child = new; 4333e12c5d1SDavid du Colombier 4349a747e4fSDavid du Colombier free(dir); 4353e12c5d1SDavid du Colombier return new; 4363e12c5d1SDavid du Colombier } 4373e12c5d1SDavid du Colombier 4383e12c5d1SDavid du Colombier void 4393e12c5d1SDavid du Colombier initroot(void) 4403e12c5d1SDavid du Colombier { 4419a747e4fSDavid du Colombier Dir *dir; 4423e12c5d1SDavid du Colombier 4433e12c5d1SDavid du Colombier root = malloc(sizeof(File)); 4443e12c5d1SDavid du Colombier if(root == 0) 4453e12c5d1SDavid du Colombier fatal("no memory"); 4463e12c5d1SDavid du Colombier 4473e12c5d1SDavid du Colombier memset(root, 0, sizeof(File)); 4489a747e4fSDavid du Colombier root->name = strdup("/"); 4499a747e4fSDavid du Colombier if(root->name == nil) 4509a747e4fSDavid du Colombier fatal("can't strdup"); 4519a747e4fSDavid du Colombier dir = dirstat(root->name); 4529a747e4fSDavid du Colombier if(dir == nil) 4533e12c5d1SDavid du Colombier fatal("root stat"); 4543e12c5d1SDavid du Colombier 4559a747e4fSDavid du Colombier root->qid.type = dir->qid.type; 4569a747e4fSDavid du Colombier root->qid.vers = dir->qid.vers; 4579a747e4fSDavid du Colombier root->qid.path = ++qid; 4589a747e4fSDavid du Colombier free(dir); 4593e12c5d1SDavid du Colombier } 4603e12c5d1SDavid du Colombier 4613e12c5d1SDavid du Colombier void 4629a747e4fSDavid du Colombier makepath(char *as, File *p, char *name) 4633e12c5d1SDavid du Colombier { 4643e12c5d1SDavid du Colombier char *c, *seg[100]; 4653e12c5d1SDavid du Colombier int i; 4669a747e4fSDavid du Colombier char *s; 4673e12c5d1SDavid du Colombier 4683e12c5d1SDavid du Colombier seg[0] = name; 4699a747e4fSDavid du Colombier for(i = 1; i < 100 && p; i++, p = p->parent){ 4703e12c5d1SDavid du Colombier seg[i] = p->name; 4719a747e4fSDavid du Colombier if(strcmp(p->name, "/") == 0) 4729a747e4fSDavid du Colombier seg[i] = ""; /* will insert slash later */ 4739a747e4fSDavid du Colombier } 4743e12c5d1SDavid du Colombier 4759a747e4fSDavid du Colombier s = as; 4763e12c5d1SDavid du Colombier while(i--) { 4773e12c5d1SDavid du Colombier for(c = seg[i]; *c; c++) 4783e12c5d1SDavid du Colombier *s++ = *c; 4793e12c5d1SDavid du Colombier *s++ = '/'; 4803e12c5d1SDavid du Colombier } 4813e12c5d1SDavid du Colombier while(s[-1] == '/') 4823e12c5d1SDavid du Colombier s--; 4833e12c5d1SDavid du Colombier *s = '\0'; 4849a747e4fSDavid du Colombier if(as == s) /* empty string is root */ 4859a747e4fSDavid du Colombier strcpy(as, "/"); 4863e12c5d1SDavid du Colombier } 4873e12c5d1SDavid du Colombier 4883e12c5d1SDavid du Colombier void 4893e12c5d1SDavid du Colombier fatal(char *s) 4903e12c5d1SDavid du Colombier { 4913e12c5d1SDavid du Colombier Proc *m; 4923e12c5d1SDavid du Colombier 4933e12c5d1SDavid du Colombier fprint(2, "iostats: %s: %r\n", s); 4943e12c5d1SDavid du Colombier 4953e12c5d1SDavid du Colombier /* Clear away the slave children */ 4963e12c5d1SDavid du Colombier for(m = Proclist; m; m = m->next) 497219b2ee8SDavid du Colombier postnote(PNPROC, m->pid, "exit"); 4983e12c5d1SDavid du Colombier 4993e12c5d1SDavid du Colombier exits("fatal"); 5003e12c5d1SDavid du Colombier } 5013e12c5d1SDavid du Colombier 5023e12c5d1SDavid du Colombier void 5033e12c5d1SDavid du Colombier runprog(char *argv[]) 5043e12c5d1SDavid du Colombier { 5053e12c5d1SDavid du Colombier char arg0[128]; 5063e12c5d1SDavid du Colombier 5073e12c5d1SDavid du Colombier exec(argv[0], argv); 5083e12c5d1SDavid du Colombier if (*argv[0] != '/' && strncmp(argv[0],"./",2) != 0) { 5093e12c5d1SDavid du Colombier sprint(arg0, "/bin/%s", argv[0]); 5103e12c5d1SDavid du Colombier exec(arg0, argv); 5113e12c5d1SDavid du Colombier } 5123e12c5d1SDavid du Colombier fatal("exec"); 5133e12c5d1SDavid du Colombier } 5143e12c5d1SDavid du Colombier 5153e12c5d1SDavid du Colombier void 5163e12c5d1SDavid du Colombier catcher(void *a, char *msg) 5173e12c5d1SDavid du Colombier { 5183e12c5d1SDavid du Colombier USED(a); 5193e12c5d1SDavid du Colombier if(strcmp(msg, DONESTR) == 0) { 5203e12c5d1SDavid du Colombier done = 1; 5213e12c5d1SDavid du Colombier noted(NCONT); 5223e12c5d1SDavid du Colombier } 5233e12c5d1SDavid du Colombier if(strcmp(msg, "exit") == 0) 5243e12c5d1SDavid du Colombier exits("exit"); 5253e12c5d1SDavid du Colombier 5263e12c5d1SDavid du Colombier noted(NDFLT); 5273e12c5d1SDavid du Colombier } 5283e12c5d1SDavid du Colombier 5293e12c5d1SDavid du Colombier void 5303e12c5d1SDavid du Colombier fidreport(Fid *f) 5313e12c5d1SDavid du Colombier { 5327dd7cddfSDavid du Colombier char *p, path[128]; 5333e12c5d1SDavid du Colombier Frec *fr; 5343e12c5d1SDavid du Colombier 5353e12c5d1SDavid du Colombier p = path; 5363e12c5d1SDavid du Colombier makepath(p, f->f, ""); 5373e12c5d1SDavid du Colombier 5383e12c5d1SDavid du Colombier for(fr = frhead; fr; fr = fr->next) { 5393e12c5d1SDavid du Colombier if(strcmp(fr->op, p) == 0) { 5403e12c5d1SDavid du Colombier fr->nread += f->nread; 541bd389b36SDavid du Colombier fr->nwrite += f->nwrite; 5423e12c5d1SDavid du Colombier fr->bread += f->bread; 5433e12c5d1SDavid du Colombier fr->bwrite += f->bwrite; 5443e12c5d1SDavid du Colombier fr->opens++; 5453e12c5d1SDavid du Colombier return; 5463e12c5d1SDavid du Colombier } 5473e12c5d1SDavid du Colombier } 5483e12c5d1SDavid du Colombier 5493e12c5d1SDavid du Colombier fr = malloc(sizeof(Frec)); 5503e12c5d1SDavid du Colombier if(fr == 0 || (fr->op = strdup(p)) == 0) 5513e12c5d1SDavid du Colombier fatal("no memory"); 5523e12c5d1SDavid du Colombier 5533e12c5d1SDavid du Colombier fr->nread = f->nread; 5543e12c5d1SDavid du Colombier fr->nwrite = f->nwrite; 5553e12c5d1SDavid du Colombier fr->bread = f->bread; 5563e12c5d1SDavid du Colombier fr->bwrite = f->bwrite; 5573e12c5d1SDavid du Colombier fr->opens = 1; 5583e12c5d1SDavid du Colombier if(frhead == 0) { 5593e12c5d1SDavid du Colombier frhead = fr; 5603e12c5d1SDavid du Colombier frtail = fr; 5613e12c5d1SDavid du Colombier } 5623e12c5d1SDavid du Colombier else { 5633e12c5d1SDavid du Colombier frtail->next = fr; 5643e12c5d1SDavid du Colombier frtail = fr; 5653e12c5d1SDavid du Colombier } 5663e12c5d1SDavid du Colombier fr->next = 0; 5673e12c5d1SDavid du Colombier } 568