typedef struct Vol Vol; // volume instance
typedef struct Fs Fs; // volume file server
typedef struct Frpc Frpc; // 9p msg.
typedef struct Prop Prop; // Attributes/properties
typedef struct Cnstr Cnstr; // Constraint
typedef struct Expr Expr; // Constraint expressions
typedef struct Mvol Mvol; // mounted volume
typedef struct Fid Fid; // guess what
enum {
Maxmsglen= IOHDRSZ + 8 * 1024, // Max message size
Biglatency= 10000, // a very bad latency
Badlatency= 200, // latency(ms) bad enough for /bin
Nthreads = 64, // # of work threads
Nattrs = 32, // Max # of attrs per constraint.
Ncnstrs= 32, // Max # of constraints per expression.
Nrpcs = 128, // Max # of allocated rpcs
Nmuxrpcs= 128, // Max # of concurrent rpcs per fs
Fhashsz = 512, // size of fid hash
Wstack = 8*1024, // Stack size for worker procs
Stack = 8*1024, // Stack size for our procs.
Tmout = 2 , // grain size for timers (ms)
Rpctmout= 20, // when to consider dead a request (20sec)
Trytmout = 60, // when to retry a dead fs (1min)
Disctick = 60, // secs for discovery protocol interval
Any = 0,
Incr = 16,
};
struct Prop {
int var;
int val;
};
struct Cnstr {
Prop attrs[Nattrs];
int nattrs;
};
struct Expr {
Cnstr* cnstrs[Ncnstrs];
int ncnstrs;
};
struct Frpc {
uchar buf[Maxmsglen]; // buf may be changed by convM2S and debug,
uchar sbuf[Maxmsglen];// we use sbuf to convS2M for sending.
char err[128]; // error message.
Dir* d; // Override dir entry for stat.
Fid* fid; // use by the fcall. Mostly for ctlfs and nilfs
Fid* freefid;// to release at the end of the fcall.
Fcall f; // 9p file call, using buf.
Fcall r; // 9p reply for the call
Frpc* rep; // buffering for the reply
int flushed;
ulong time; // for the request
Frpc* next; // in free list or mux list
Channel*sc; // where to notify the thread waiting to this
};
struct Mvol {
Ref; // how many fids using it. Including attach
QLock; // for vols and fids
long epoch; // of last updatemvol
int isunion; // true for volume unions.
int musthave; // can't fail. Hold rpcs if no vol avail.
int notimeout; // don't timeout RPCs other than walk on this.
char* spec; // attach spec. for debugging
char* name; // name for the volume mounted
Expr cnstr; // constraint expression
int choice; // which cnstr in expr are we using?
Vol** vols; // volumes mounted by this mount point.
int nvols;
Fid* fids; // using this mvol.
int debug; // debug this mount point.
};
struct Vol {
Ref; // # of mvols mounting it
long epoch; // tstamp for addition/death
int dead; // volume not available
int disabled; // volume disabled by user
char* cfname; // config file where we discovered it.
char* host; // servicing it.
char* addr; // where to reach the server
char* spec; // for the file tree
Name* sname; // path in server to / of vol
char* name; // for the volume
char* cnstr; // constraint as supplied by user
Cnstr ccnstr; // compiled constraints
Fs* fs; // connection to server
Fid* slash; // fid to / for vol.
};
struct Fs {
Ref; // # of vols relying on it.
long epoch; // tstamp for addition/death
int fd; // to server
int musthave;// at least one fid requested as *must* this fs.
Qid fdqid; // qid for /srv file to server. For amountfs.
long time; // when last op was started or declared dead
char* addr; // where to reach the 9p server
char* raddr; // addr once resolved by cs (cached)
char* spec; // for its tree in attach
Frpc* rpcs; // list of active rpcs
Channel*reqc; // of Freq, to send requests.
Channel*repc; // replies from the fs read proc sent here
Channel*tmrc; // periodic tick for this fs
int pid; // of read proc
Fid* fid; // for slash, while attached
Qid qid; // used to decorate real qids for fids
long lat; // ms needed to mount the fs.
};
struct Fid {
QLock;
Fid* hnext; // on hash or freelist
Fid* mnext; // on Mvol
int linked; // on Mvol through mnext
int epoch; // for its fs when fid was bound to it.
int stale; // true when fid goes to a gone volume in its mvol
Mvol* mvol; // client's mount point where it resides
Name* sname; // relative path for file in volume (server name)
int nr; // fid number used by client (we hash on it)
int snr; // fid number used to talk to the server
Dir* d;
Qid qid; // first qid seen by client
Fs* fs; // Nil or FS for this fid when snr is valid.
int notimeout;// true if should not tmout reqs other than walk
int isopen; // true if fid is open
int omode; // open mode when open
int iounit;
char* ureadbuf;// for reading unions and ctl files
long ureadlen;
int debug; // true if fid is being debugged
};
typedef void (*Fscall)(Frpc*);
#pragma varargck type "V" Vol*
#pragma varargck type "W" Mvol*
#pragma varargck type "X" Fid*
#pragma varargck type "K" Expr*
#pragma varargck type "k" Cnstr*
Frpc* rpcalloc(void);
Name* n_new(void);
void adsproc(void*);
void dumpfids(void);
void dumpfss(void);
void dumpmvols(void);
void dumpvols(void);
void exprinit(void);
void fsmuxthread(void*arg);
void sendads(void);
Fid * fidalloc(int nr);
int postfd(char *name, int pfd);
int noop(Fs* , Frpc* fop);
Fs* getfs(char* addr, char* spec);
int getfidnr(void);
void threadmain(int argc, char *argv[]);
void putfs(Fs* c);
void cnstrcat(Cnstr* c1, Cnstr* c2);
void n_cat(Name* cn, Name* n);
void exprfree(Expr* e);
int cnstrmatch(Cnstr* env, Cnstr* c);
int exprmatch(Cnstr* env, Expr* exp);
int Vfmt(Fmt* f);
int Wfmt(Fmt* f);
int namefmt(Fmt* f);
int getfcall(int fd, Frpc* m);
int getfrep(int fd, Frpc* m);
int putfcall(int fd, Frpc* m);
int putfrep(int fd, Frpc* m);
int walkfid(Fid* fid, Fid* nfid, char** elems, int nelems, Frpc* fop);
int fidfree(Fid* fid, Frpc* fop);
int Kfmt(Fmt* fmt);
int fidfmt(Fmt* fmt);
int kfmt(Fmt* fmt);
void config(char* fname);
int checkvols(Frpc* fop);
void rpcerr(Frpc* fop, char* err);
int amountfs(Fs* fs);
int fsop(Fs* fs, Frpc* op);
int islocal(char* host);
Cnstr* parsecnstr(char* ln, Cnstr* c);
Expr* parseexpr(char* ln, Expr* e);
void cmdline(char* ln, char* fname, int lno);
void putmvol(Mvol* m, Frpc* fop);
void rpcfree(Frpc* m);
void mvoladdfid(Mvol* m, Fid* fid);
void mvoldelfid(Mvol* m, Fid* fid);
void updatemvol(Mvol* m, Frpc* fop);
Fid* mvolgetfid(Mvol* m, Name* sname, Fid* excl);
void mvolunmount(Mvol* m, Vol* v, Frpc* fop);
Vol* getmvolvol(Mvol* m, int i);
void n_dotdot(Name* n);
void n_free(Name* n);
void n_reset(Name* n);
void n_append(Name* n, char* s);
void n_setpos(Name* n, int a, int b);
void n_getpos(Name* n, int* a, int* b);
int n_eq(Name* n1, Name* n2);
void fstimer(ulong now);
void* erealloc(void* p, int sz);
char* estrdup(char* s);
Mvol* newmvol(char* spec);
void* emalloc(int sz);
void deadvol(Vol* v, Frpc* fop);
int volmount(Vol* v, Frpc* fop);
void closefid(Fid* f, Frpc* fop);
void fsstats(void);
void fdconfig(int,char*);
void newfsqid(Qid*);
void mvoldelotherfids(Mvol* m, Fid* fid);
#define dprint if(debug)fprint
#define vdprint if(vdebug)fprint
void dbgprint (Fid*,char*,...);
void Dbgprint (Fid*, char*,...);
void tracemvol(char*,int);
#pragma varargck argpos dbgprint 2
#pragma varargck argpos Dbgprint 2
extern int debug, vdebug, hdebug;
extern Fscall fscalls[Tmax];
extern Vol** vols;
extern int nvols;
extern QLock volslck;
extern Mvol** mvols;
extern int nmvols;
extern QLock mvolslck;
extern Ref epoch;
extern int dontsendads;
extern int msglen;
extern Fs ctlfs;
extern int (*(ctlfsops[]))(Fs*,Frpc*);
extern int (*(nilfsops[]))(Fs*,Frpc*);
extern uvlong Ctldirqid;
extern uvlong Ctlqid;
extern Cnstr netokcnstr, netbadcnstr;
extern char Eopen[];
extern char Enotopen[];
extern char Eio[];
extern char Eperm[];
extern char Enotexist[];
extern char Eauth[];
extern char Euser[];
extern char Espec[];
extern char Edupfid[];
extern char Ebadfid[];
|