123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include <u.h>
- #include <libc.h>
- #include <auth.h>
- #include <fcall.h>
- #include "cformat.h"
- #include "lru.h"
- #include "bcache.h"
- #include "disk.h"
- #include "inode.h"
- #include "file.h"
- #include "stats.h"
- enum
- {
- Nfid= 10240,
- };
- /* maximum length of a file */
- enum { MAXLEN = ~0ULL >> 1 };
- typedef struct Mfile Mfile;
- typedef struct Ram Ram;
- typedef struct P9fs P9fs;
- struct Mfile
- {
- Qid qid;
- char busy;
- };
- Mfile mfile[Nfid];
- Icache ic;
- int debug, statson, noauth, openserver;
- struct P9fs
- {
- int fd[2];
- Fcall rhdr;
- Fcall thdr;
- int32_t len;
- char *name;
- };
- P9fs c; /* client conversation */
- P9fs s; /* server conversation */
- struct Cfsstat cfsstat, cfsprev;
- char statbuf[2048];
- int statlen;
- #define MAXFDATA 8192 /* i/o size for read/write */
- int messagesize = MAXFDATA+IOHDRSZ;
- uint8_t datasnd[MAXFDATA + IOHDRSZ];
- uint8_t datarcv[MAXFDATA + IOHDRSZ];
- Qid rootqid;
- Qid ctlqid = {0x5555555555555555LL, 0, 0};
- void rversion(void);
- void rauth(Mfile*);
- void rflush(void);
- void rattach(Mfile*);
- void rwalk(Mfile*);
- void ropen(Mfile*);
- void rcreate(Mfile*);
- void rread(Mfile*);
- void rwrite(Mfile*);
- void rclunk(Mfile*);
- void rremove(Mfile*);
- void rstat(Mfile*);
- void rwstat(Mfile*);
- void error(char*, ...);
- void warning(char*);
- void mountinit(char*, char*);
- void io(void);
- void sendreply(char*);
- void sendmsg(P9fs*, Fcall*);
- void rcvmsg(P9fs*, Fcall*);
- int delegate(void);
- int askserver(void);
- void cachesetup(int, char*, char*);
- int ctltest(Mfile*);
- void genstats(void);
- char *mname[]={
- [Tversion] "Tversion",
- [Tauth] "Tauth",
- [Tflush] "Tflush",
- [Tattach] "Tattach",
- [Twalk] "Twalk",
- [Topen] "Topen",
- [Tcreate] "Tcreate",
- [Tclunk] "Tclunk",
- [Tread] "Tread",
- [Twrite] "Twrite",
- [Tremove] "Tremove",
- [Tstat] "Tstat",
- [Twstat] "Twstat",
- [Rversion] "Rversion",
- [Rauth] "Rauth",
- [Rerror] "Rerror",
- [Rflush] "Rflush",
- [Rattach] "Rattach",
- [Rwalk] "Rwalk",
- [Ropen] "Ropen",
- [Rcreate] "Rcreate",
- [Rclunk] "Rclunk",
- [Rread] "Rread",
- [Rwrite] "Rwrite",
- [Rremove] "Rremove",
- [Rstat] "Rstat",
- [Rwstat] "Rwstat",
- 0,
- };
- void
- usage(void)
- {
- fprint(2, "usage:\tcfs -s [-dknrS] [-f partition]\n");
- fprint(2, "\tcfs [-a netaddr | -F srv] [-dknrS] [-f partition] [mntpt]\n");
- exits("usage");
- }
- void
- main(int argc, char *argv[])
- {
- int std, format, chkid;
- char *part, *server, *mtpt;
- NetConnInfo *snci;
- std = 0;
- format = 0;
- chkid = 1;
- part = "/dev/sdC0/cache";
- server = "tcp!fs";
- mtpt = "/tmp";
- ARGBEGIN{
- case 'a':
- server = EARGF(usage());
- break;
- case 'd':
- debug = 1;
- break;
- case 'f':
- part = EARGF(usage());
- break;
- case 'F':
- server = EARGF(usage());
- openserver = 1;
- break;
- case 'k':
- chkid = 0;
- break;
- case 'n':
- noauth = 1;
- break;
- case 'r':
- format = 1;
- break;
- case 'S':
- statson = 1;
- break;
- case 's':
- std = 1;
- break;
- default:
- usage();
- }ARGEND
- if(argc && *argv)
- mtpt = *argv;
- if(debug)
- fmtinstall('F', fcallfmt);
- c.name = "client";
- s.name = "server";
- if(std){
- c.fd[0] = c.fd[1] = 1;
- s.fd[0] = s.fd[1] = 0;
- }else
- mountinit(server, mtpt);
- if(chkid){
- if((snci = getnetconninfo(nil, s.fd[0])) == nil)
- /* Failed to lookup information; format */
- cachesetup(1, nil, part);
- else
- /* Do partition check */
- cachesetup(0, snci->raddr, part);
- }else
- /* Obey -f w/o regard to cache vs. remote server */
- cachesetup(format, nil, part);
- switch(fork()){
- case 0:
- io();
- exits("");
- case -1:
- error("fork");
- default:
- exits("");
- }
- }
- void
- cachesetup(int format, char *name, char *partition)
- {
- int f;
- int secsize;
- int inodes;
- int blocksize;
- secsize = 512;
- inodes = 1024;
- blocksize = 4*1024;
- f = open(partition, ORDWR);
- if(f < 0)
- error("opening partition");
- if(format || iinit(&ic, f, secsize, name) < 0){
- /*
- * If we need to format and don't have a name, fall
- * back to our old behavior of using "bootes"
- */
- name = (name == nil? "bootes": name);
- if(iformat(&ic, f, inodes, name, blocksize, secsize) < 0)
- error("formatting failed");
- }
- }
- void
- mountinit(char *server, char *mountpoint)
- {
- int err;
- int p[2];
- /*
- * grab a channel and call up the file server
- */
- if (openserver)
- s.fd[0] = open(server, ORDWR);
- else
- s.fd[0] = dial(netmkaddr(server, 0, "9fs"), 0, 0, 0);
- if(s.fd[0] < 0)
- error("opening data: %r");
- s.fd[1] = s.fd[0];
- /*
- * mount onto name space
- */
- if(pipe(p) < 0)
- error("pipe failed");
- switch(fork()){
- case 0:
- break;
- default:
- if (noauth)
- err = mount(p[1], -1, mountpoint, MREPL|MCREATE, "",
- 'M');
- else
- err = amount(p[1], mountpoint, MREPL|MCREATE, "");
- if (err < 0)
- error("mount failed: %r");
- exits(0);
- case -1:
- error("fork failed\n");
- /*BUG: no wait!*/
- }
- c.fd[0] = c.fd[1] = p[0];
- }
- void
- io(void)
- {
- int type;
- Mfile *mf;
- loop:
- rcvmsg(&c, &c.thdr);
- type = c.thdr.type;
- if(statson){
- cfsstat.cm[type].n++;
- cfsstat.cm[type].s = nsec();
- }
- mf = &mfile[c.thdr.fid];
- switch(type){
- default:
- error("type");
- break;
- case Tversion:
- rversion();
- break;
- case Tauth:
- mf = &mfile[c.thdr.afid];
- rauth(mf);
- break;
- case Tflush:
- rflush();
- break;
- case Tattach:
- rattach(mf);
- break;
- case Twalk:
- rwalk(mf);
- break;
- case Topen:
- ropen(mf);
- break;
- case Tcreate:
- rcreate(mf);
- break;
- case Tread:
- rread(mf);
- break;
- case Twrite:
- rwrite(mf);
- break;
- case Tclunk:
- rclunk(mf);
- break;
- case Tremove:
- rremove(mf);
- break;
- case Tstat:
- rstat(mf);
- break;
- case Twstat:
- rwstat(mf);
- break;
- }
- if(statson){
- cfsstat.cm[type].t += nsec() -cfsstat.cm[type].s;
- }
- goto loop;
- }
- void
- rversion(void)
- {
- if(messagesize > c.thdr.msize)
- messagesize = c.thdr.msize;
- c.thdr.msize = messagesize; /* set downstream size */
- delegate();
- }
- void
- rauth(Mfile *mf)
- {
- if(mf->busy)
- error("auth to used channel");
- if(delegate() == 0){
- mf->qid = s.rhdr.aqid;
- mf->busy = 1;
- }
- }
- void
- rflush(void) /* synchronous so easy */
- {
- sendreply(0);
- }
- void
- rattach(Mfile *mf)
- {
- if(delegate() == 0){
- mf->qid = s.rhdr.qid;
- mf->busy = 1;
- if (statson == 1){
- statson++;
- rootqid = mf->qid;
- }
- }
- }
- void
- rwalk(Mfile *mf)
- {
- Mfile *nmf;
- nmf = nil;
- if(statson
- && mf->qid.type == rootqid.type && mf->qid.path == rootqid.path
- && c.thdr.nwname == 1 && strcmp(c.thdr.wname[0], "cfsctl") == 0){
- /* This is the ctl file */
- nmf = &mfile[c.thdr.newfid];
- if(c.thdr.newfid != c.thdr.fid && nmf->busy)
- error("clone to used channel");
- nmf = &mfile[c.thdr.newfid];
- nmf->qid = ctlqid;
- nmf->busy = 1;
- c.rhdr.nwqid = 1;
- c.rhdr.wqid[0] = ctlqid;
- sendreply(0);
- return;
- }
- if(c.thdr.newfid != c.thdr.fid){
- if(c.thdr.newfid >= Nfid)
- error("clone nfid out of range");
- nmf = &mfile[c.thdr.newfid];
- if(nmf->busy)
- error("clone to used channel");
- nmf = &mfile[c.thdr.newfid];
- nmf->qid = mf->qid;
- nmf->busy = 1;
- mf = nmf; /* Walk mf */
- }
- if(delegate() < 0){ /* complete failure */
- if(nmf)
- nmf->busy = 0;
- return;
- }
- if(s.rhdr.nwqid == c.thdr.nwname){ /* complete success */
- if(s.rhdr.nwqid > 0)
- mf->qid = s.rhdr.wqid[s.rhdr.nwqid-1];
- return;
- }
- /* partial success; release fid */
- if(nmf)
- nmf->busy = 0;
- }
- void
- ropen(Mfile *mf)
- {
- if(statson && ctltest(mf)){
- /* Opening ctl file */
- if(c.thdr.mode != OREAD){
- sendreply("does not exist");
- return;
- }
- c.rhdr.qid = ctlqid;
- c.rhdr.iounit = 0;
- sendreply(0);
- genstats();
- return;
- }
- if(delegate() == 0){
- mf->qid = s.rhdr.qid;
- if(c.thdr.mode & OTRUNC)
- iget(&ic, mf->qid);
- }
- }
- void
- rcreate(Mfile *mf)
- {
- if(statson && ctltest(mf)){
- sendreply("exists");
- return;
- }
- if(delegate() == 0){
- mf->qid = s.rhdr.qid;
- mf->qid.vers++;
- }
- }
- void
- rclunk(Mfile *mf)
- {
- if(!mf->busy){
- sendreply(0);
- return;
- }
- mf->busy = 0;
- delegate();
- }
- void
- rremove(Mfile *mf)
- {
- if(statson && ctltest(mf)){
- sendreply("not removed");
- return;
- }
- mf->busy = 0;
- delegate();
- }
- void
- rread(Mfile *mf)
- {
- int cnt, done;
- int32_t n;
- int64_t off, first;
- char *cp;
- char data[MAXFDATA];
- Ibuf *b;
- off = c.thdr.offset;
- first = off;
- cnt = c.thdr.count;
- if(statson && ctltest(mf)){
- if(cnt > statlen-off)
- c.rhdr.count = statlen-off;
- else
- c.rhdr.count = cnt;
- if((int)c.rhdr.count < 0){
- sendreply("eof");
- return;
- }
- c.rhdr.data = statbuf + off;
- sendreply(0);
- return;
- }
- if(mf->qid.type & (QTDIR|QTAUTH)){
- delegate();
- if (statson) {
- cfsstat.ndirread++;
- if(c.rhdr.count > 0){
- cfsstat.bytesread += c.rhdr.count;
- cfsstat.bytesfromdirs += c.rhdr.count;
- }
- }
- return;
- }
- b = iget(&ic, mf->qid);
- if(b == 0){
- DPRINT(2, "delegating read\n");
- delegate();
- if (statson){
- cfsstat.ndelegateread++;
- if(c.rhdr.count > 0){
- cfsstat.bytesread += c.rhdr.count;
- cfsstat.bytesfromserver += c.rhdr.count;
- }
- }
- return;
- }
- cp = data;
- done = 0;
- while(cnt>0 && !done){
- if(off >= b->inode.length){
- DPRINT(2, "offset %lld greater than length %lld\n",
- off, b->inode.length);
- break;
- }
- n = fread(&ic, b, cp, off, cnt);
- if(n <= 0){
- n = -n;
- if(n==0 || n>cnt)
- n = cnt;
- DPRINT(2,
- "fetch %ld bytes of data from server at offset %lld\n",
- n, off);
- s.thdr.type = c.thdr.type;
- s.thdr.fid = c.thdr.fid;
- s.thdr.tag = c.thdr.tag;
- s.thdr.offset = off;
- s.thdr.count = n;
- if(statson)
- cfsstat.ndelegateread++;
- if(askserver() < 0){
- sendreply(s.rhdr.ename);
- return;
- }
- if(s.rhdr.count != n)
- done = 1;
- n = s.rhdr.count;
- if(n == 0){
- /* end of file */
- if(b->inode.length > off){
- DPRINT(2, "file %llud.%ld, length %lld\n",
- b->inode.qid.path,
- b->inode.qid.vers, off);
- b->inode.length = off;
- }
- break;
- }
- memmove(cp, s.rhdr.data, n);
- fwrite(&ic, b, cp, off, n);
- if (statson){
- cfsstat.bytestocache += n;
- cfsstat.bytesfromserver += n;
- }
- }else{
- DPRINT(2, "fetched %ld bytes from cache\n", n);
- if(statson)
- cfsstat.bytesfromcache += n;
- }
- cnt -= n;
- off += n;
- cp += n;
- }
- c.rhdr.data = data;
- c.rhdr.count = off - first;
- if(statson)
- cfsstat.bytesread += c.rhdr.count;
- sendreply(0);
- }
- void
- rwrite(Mfile *mf)
- {
- Ibuf *b;
- char buf[MAXFDATA];
- if(statson && ctltest(mf)){
- sendreply("read only");
- return;
- }
- if(mf->qid.type & (QTDIR|QTAUTH)){
- delegate();
- if(statson && c.rhdr.count > 0)
- cfsstat.byteswritten += c.rhdr.count;
- return;
- }
- memmove(buf, c.thdr.data, c.thdr.count);
- if(delegate() < 0)
- return;
- if(s.rhdr.count > 0)
- cfsstat.byteswritten += s.rhdr.count;
- /* don't modify our cache for append-only data; always read from server*/
- if(mf->qid.type & QTAPPEND)
- return;
- b = iget(&ic, mf->qid);
- if(b == 0)
- return;
- if (b->inode.length < c.thdr.offset + s.rhdr.count)
- b->inode.length = c.thdr.offset + s.rhdr.count;
- mf->qid.vers++;
- if (s.rhdr.count != c.thdr.count)
- syslog(0, "cfslog", "rhdr.count %ud, thdr.count %ud\n",
- s.rhdr.count, c.thdr.count);
- if(fwrite(&ic, b, buf, c.thdr.offset, s.rhdr.count) == s.rhdr.count){
- iinc(&ic, b);
- if(statson)
- cfsstat.bytestocache += s.rhdr.count;
- }
- }
- void
- rstat(Mfile *mf)
- {
- Dir d;
- if(statson && ctltest(mf)){
- genstats();
- d.qid = ctlqid;
- d.mode = 0444;
- d.length = statlen; /* would be nice to do better */
- d.name = "cfsctl";
- d.uid = "none";
- d.gid = "none";
- d.muid = "none";
- d.atime = time(nil);
- d.mtime = d.atime;
- c.rhdr.nstat = convD2M(&d, c.rhdr.stat,
- sizeof c.rhdr - (c.rhdr.stat - (uint8_t*)&c.rhdr));
- sendreply(0);
- return;
- }
- if(delegate() == 0){
- Ibuf *b;
- convM2D(s.rhdr.stat, s.rhdr.nstat , &d, nil);
- mf->qid = d.qid;
- b = iget(&ic, mf->qid);
- if(b)
- b->inode.length = d.length;
- }
- }
- void
- rwstat(Mfile *mf)
- {
- Ibuf *b;
- if(statson && ctltest(mf)){
- sendreply("read only");
- return;
- }
- delegate();
- if(b = iget(&ic, mf->qid))
- b->inode.length = MAXLEN;
- }
- void
- error(char *fmt, ...)
- {
- va_list arg;
- static char buf[2048];
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- fprint(2, "%s: %s\n", argv0, buf);
- exits("error");
- }
- void
- warning(char *s)
- {
- fprint(2, "cfs: %s: %r\n", s);
- }
- /*
- * send a reply to the client
- */
- void
- sendreply(char *err)
- {
- if(err){
- c.rhdr.type = Rerror;
- c.rhdr.ename = err;
- }else{
- c.rhdr.type = c.thdr.type+1;
- c.rhdr.fid = c.thdr.fid;
- }
- c.rhdr.tag = c.thdr.tag;
- sendmsg(&c, &c.rhdr);
- }
- /*
- * send a request to the server, get the reply, and send that to
- * the client
- */
- int
- delegate(void)
- {
- int type;
- type = c.thdr.type;
- if(statson){
- cfsstat.sm[type].n++;
- cfsstat.sm[type].s = nsec();
- }
- sendmsg(&s, &c.thdr);
- rcvmsg(&s, &s.rhdr);
- if(statson)
- cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s;
- sendmsg(&c, &s.rhdr);
- return c.thdr.type+1 == s.rhdr.type ? 0 : -1;
- }
- /*
- * send a request to the server and get a reply
- */
- int
- askserver(void)
- {
- int type;
- s.thdr.tag = c.thdr.tag;
- type = s.thdr.type;
- if(statson){
- cfsstat.sm[type].n++;
- cfsstat.sm[type].s = nsec();
- }
- sendmsg(&s, &s.thdr);
- rcvmsg(&s, &s.rhdr);
- if(statson)
- cfsstat.sm[type].t += nsec() - cfsstat.sm[type].s;
- return s.thdr.type+1 == s.rhdr.type ? 0 : -1;
- }
- /*
- * send/receive messages with logging
- */
- void
- sendmsg(P9fs *p, Fcall *f)
- {
- DPRINT(2, "->%s: %F\n", p->name, f);
- p->len = convS2M(f, datasnd, messagesize);
- if(p->len <= 0)
- error("convS2M");
- if(write(p->fd[1], datasnd, p->len)!=p->len)
- error("sendmsg");
- }
- void
- dump(uint8_t *p, int len)
- {
- fprint(2, "%d bytes", len);
- while(len-- > 0)
- fprint(2, " %.2ux", *p++);
- fprint(2, "\n");
- }
- void
- rcvmsg(P9fs *p, Fcall *f)
- {
- int olen, rlen;
- char buf[128];
- olen = p->len;
- p->len = read9pmsg(p->fd[0], datarcv, sizeof(datarcv));
- if(p->len <= 0){
- snprint(buf, sizeof buf, "read9pmsg(%d)->%ld: %r",
- p->fd[0], p->len);
- error(buf);
- }
- if((rlen = convM2S(datarcv, p->len, f)) != p->len)
- error("rcvmsg format error, expected length %d, got %d",
- rlen, p->len);
- if(f->fid >= Nfid){
- fprint(2, "<-%s: %d %s on %d\n", p->name, f->type,
- mname[f->type]? mname[f->type]: "mystery", f->fid);
- dump((uint8_t*)datasnd, olen);
- dump((uint8_t*)datarcv, p->len);
- error("rcvmsg fid out of range");
- }
- DPRINT(2, "<-%s: %F\n", p->name, f);
- }
- int
- ctltest(Mfile *mf)
- {
- return mf->busy && mf->qid.type == ctlqid.type &&
- mf->qid.path == ctlqid.path;
- }
- void
- genstats(void)
- {
- int i;
- char *p;
- p = statbuf;
- p += snprint(p, sizeof statbuf+statbuf-p,
- " Client Server\n");
- p += snprint(p, sizeof statbuf+statbuf-p,
- " #calls Δ ms/call Δ #calls Δ ms/call Δ\n");
- for (i = 0; i < nelem(cfsstat.cm); i++)
- if(cfsstat.cm[i].n || cfsstat.sm[i].n) {
- p += snprint(p, sizeof statbuf+statbuf-p,
- "%7lud %7lud ", cfsstat.cm[i].n,
- cfsstat.cm[i].n - cfsprev.cm[i].n);
- if (cfsstat.cm[i].n)
- p += snprint(p, sizeof statbuf+statbuf-p,
- "%7.3f ", 0.000001*cfsstat.cm[i].t/
- cfsstat.cm[i].n);
- else
- p += snprint(p, sizeof statbuf+statbuf-p,
- " ");
- if(cfsstat.cm[i].n - cfsprev.cm[i].n)
- p += snprint(p, sizeof statbuf+statbuf-p,
- "%7.3f ", 0.000001*
- (cfsstat.cm[i].t - cfsprev.cm[i].t)/
- (cfsstat.cm[i].n - cfsprev.cm[i].n));
- else
- p += snprint(p, sizeof statbuf+statbuf-p,
- " ");
- p += snprint(p, sizeof statbuf+statbuf-p,
- "%7lud %7lud ", cfsstat.sm[i].n,
- cfsstat.sm[i].n - cfsprev.sm[i].n);
- if (cfsstat.sm[i].n)
- p += snprint(p, sizeof statbuf+statbuf-p,
- "%7.3f ", 0.000001*cfsstat.sm[i].t/
- cfsstat.sm[i].n);
- else
- p += snprint(p, sizeof statbuf+statbuf-p,
- " ");
- if(cfsstat.sm[i].n - cfsprev.sm[i].n)
- p += snprint(p, sizeof statbuf+statbuf-p,
- "%7.3f ", 0.000001*
- (cfsstat.sm[i].t - cfsprev.sm[i].t)/
- (cfsstat.sm[i].n - cfsprev.sm[i].n));
- else
- p += snprint(p, sizeof statbuf+statbuf-p,
- " ");
- p += snprint(p, sizeof statbuf+statbuf-p, "%s\n",
- mname[i]);
- }
- p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndirread\n",
- cfsstat.ndirread, cfsstat.ndirread - cfsprev.ndirread);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelegateread\n",
- cfsstat.ndelegateread, cfsstat.ndelegateread -
- cfsprev.ndelegateread);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ninsert\n",
- cfsstat.ninsert, cfsstat.ninsert - cfsprev.ninsert);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud ndelete\n",
- cfsstat.ndelete, cfsstat.ndelete - cfsprev.ndelete);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7lud %7lud nupdate\n",
- cfsstat.nupdate, cfsstat.nupdate - cfsprev.nupdate);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesread\n",
- cfsstat.bytesread, cfsstat.bytesread - cfsprev.bytesread);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud byteswritten\n",
- cfsstat.byteswritten, cfsstat.byteswritten -
- cfsprev.byteswritten);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromserver\n",
- cfsstat.bytesfromserver, cfsstat.bytesfromserver -
- cfsprev.bytesfromserver);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromdirs\n",
- cfsstat.bytesfromdirs, cfsstat.bytesfromdirs -
- cfsprev.bytesfromdirs);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytesfromcache\n",
- cfsstat.bytesfromcache, cfsstat.bytesfromcache -
- cfsprev.bytesfromcache);
- p += snprint(p, sizeof statbuf+statbuf-p, "%7llud %7llud bytestocache\n",
- cfsstat.bytestocache, cfsstat.bytestocache -
- cfsprev.bytestocache);
- statlen = p - statbuf;
- cfsprev = cfsstat;
- }
|