📄 cfs.c
字号:
#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 */#define MAXLEN 0x7fffffffffffffffLLtypedef 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;struct P9fs{ int fd[2]; Fcall rhdr; Fcall thdr; long 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;uchar datasnd[MAXFDATA + IOHDRSZ];uchar 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*);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,};voidusage(void){ fprint(2, "usage:\tcfs -s [-rd] [-f partition]"); fprint(2, "\tcfs [-rd] [-f partition] [-a netaddr] [mt-pt]\n"); exits("usage");}voidmain(int argc, char *argv[]){ int std; int format; char *part; char *server; char *mtpt; std = 0; format = 0; part = "/dev/sdC0/cache"; server = "il!emelie"; mtpt = "/tmp"; ARGBEGIN{ case 'a': server = ARGF(); if(server == 0) usage(); break; case 'S': statson = 1; break; case 's': std = 1; break; case 'r': format = 1; break; case 'f': part = ARGF(); if(part == 0) usage(); break; case 'd': debug = 1; break; default: usage(); }ARGEND if(argc && *argv) mtpt = *argv; if(debug) fmtinstall('F', fcallfmt); cachesetup(format, part); 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); switch(fork()){ case 0: io(); exits(""); case -1: error("fork"); default: exits(""); }}voidcachesetup(int format, 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)<0){ if(iformat(&ic, f, inodes, "bootes", blocksize, secsize) < 0) error("formatting failed"); }}voidmountinit(char *server, char *mountpoint){ int p[2]; /* * grab a channel and call up the file server */ s.fd[0] = s.fd[1] = dial(netmkaddr(server, 0, "9fs"), 0, 0, 0); if(s.fd[0] < 0) error("opening data"); /* * mount onto name space */ if(pipe(p) < 0) error("pipe failed"); switch(fork()){ case 0: break; default: if(amount(p[1], mountpoint, MREPL|MCREATE, "") < 0) error("mount failed"); exits(0); case -1: error("fork failed\n");/*BUG: no wait!*/ } c.fd[0] = c.fd[1] = p[0];}voidio(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;}voidrversion(void){ if(messagesize > c.thdr.msize) messagesize = c.thdr.msize; c.thdr.msize = messagesize; /* set downstream size */ delegate();}voidrauth(Mfile *mf){ if(mf->busy) error("auth to used channel"); if(delegate() == 0){ mf->qid = s.rhdr.aqid; mf->busy = 1; }}voidrflush(void) /* synchronous so easy */{ sendreply(0);}voidrattach(Mfile *mf){ if(delegate() == 0){ mf->qid = s.rhdr.qid; mf->busy = 1; if (statson == 1){ statson++; rootqid = mf->qid; } }}voidrwalk(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;}voidropen(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); }}voidrcreate(Mfile *mf){ if(statson && ctltest(mf)){ sendreply("exists"); return; } if(delegate() == 0){ mf->qid = s.rhdr.qid; mf->qid.vers++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -