/* * fundamental constants and types of the implementation * changing any of these changes the layout on disk */ enum { SUPER_ADDR = 2, /* block address of superblock */ ROOT_ADDR = 3, /* block address of root directory */ }; /* more fundamental types */ typedef vlong Wideoff; /* type to widen Off to for printing; ≥ as wide as Off */ typedef short Userid; /* signed internal representation of user-id */ typedef long Timet; /* in seconds since epoch */ typedef vlong Devsize; /* in bytes */ /* macros */ #define NEXT(x, l) (((x)+1) % (l)) #define PREV(x, l) ((x) == 0? (l)-1: (x)-1) #define HOWMANY(x, y) (((x)+((y)-1)) / (y)) #define ROUNDUP(x, y) (HOWMANY((x), (y)) * (y)) #define TK2MS(t) (((ulong)(t)*1000)/HZ) /* ticks to ms - beware rounding */ #define MS2TK(t) (((ulong)(t)*HZ)/1000) /* ms to ticks - beware rounding */ #define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ /* constants that don't affect disk layout */ enum { MAXDAT = 8192, /* max allowable data message */ MAXMSG = 128, /* max protocol message sans data */ MB = 1024*1024, HZ = 1, /* clock frequency */ }; /* * tunable parameters */ enum { Maxword = 256, /* max bytes per command-line word */ NTLOCK = 200, /* number of active file Tlocks */ }; typedef struct Auth Auth; typedef struct Bp Bp; typedef struct Bucket Bucket; typedef struct Cache Cache; typedef struct Centry Centry; typedef struct Chan Chan; typedef struct Command Command; typedef struct Conf Conf; typedef struct Cons Cons; typedef struct Dentry Dentry; typedef struct Device Device; typedef struct Fbuf Fbuf; typedef struct File File; typedef struct Filsys Filsys; typedef struct Filter Filter; typedef struct Flag Flag; typedef struct Hiob Hiob; typedef struct Iobuf Iobuf; typedef struct Lock Lock; typedef struct Msgbuf Msgbuf; typedef struct QLock QLock; typedef struct Qid9p1 Qid9p1; typedef struct Queue Queue; typedef union Rabuf Rabuf; typedef struct Rendez Rendez; typedef struct Rtc Rtc; typedef struct Startsb Startsb; typedef struct Super1 Super1; typedef struct Superb Superb; typedef struct Tag Tag; typedef struct Time Time; typedef struct Tlock Tlock; typedef struct Tm Tm; typedef struct Uid Uid; typedef struct Wpath Wpath; #pragma incomplete Auth struct Tag { short pad; /* make tag end at a long boundary */ short tag; Off path; }; /* DONT TOUCH, this is the disk structure */ struct Qid9p1 { Off path; /* was long */ ulong version; /* should be Off */ }; /* DONT TOUCH, this is the disk structure */ struct Super1 { Off fstart; Off fsize; Off tfree; Off qidgen; /* generator for unique ids */ /* * Stuff for WWC device */ Off cwraddr; /* cfs root addr */ Off roraddr; /* dump root addr */ Off last; /* last super block addr */ Off next; /* next super block addr */ }; /* DONT TOUCH, this is the disk structure */ struct Centry { ushort age; short state; Off waddr; /* worm addr */ }; /* DONT TOUCH, this is the disk structure */ struct Dentry { char name[NAMELEN]; Userid uid; Userid gid; ushort mode; #define DALLOC 0x8000 #define DDIR 0x4000 #define DAPND 0x2000 #define DLOCK 0x1000 #define DREAD 0x4 #define DWRITE 0x2 #define DEXEC 0x1 Userid muid; Qid9p1 qid; Off size; Off dblock[NDBLOCK]; Off iblocks[NIBLOCK]; long atime; long mtime; }; /* * derived constants */ enum { BUFSIZE = RBUFSIZE - sizeof(Tag), DIRPERBUF = BUFSIZE / sizeof(Dentry), INDPERBUF = BUFSIZE / sizeof(Off), FEPERBUF = (BUFSIZE-sizeof(Super1)-sizeof(Off)) / sizeof(Off), SMALLBUF = MAXMSG, LARGEBUF = MAXMSG+MAXDAT+256, RAGAP = (300*1024)/BUFSIZE, /* readahead parameter */ BKPERBLK = 10, CEPERBK = (BUFSIZE - BKPERBLK*sizeof(Off)) / (sizeof(Centry)*BKPERBLK), }; /* * send/recv queue structure */ struct Queue { QLock; /* to manipulate values */ Rendez empty; Rendez full; int waitedfor; /* flag */ char* name; /* for debugging */ int size; /* size of queue */ int loc; /* circular pointer */ int count; /* how many in queue */ void* args[1]; /* list of saved pointers, [->size] */ }; struct Device { uchar type; uchar init; Device* link; /* link for mcat/mlev/mirror */ Device* dlink; /* link all devices */ void* private; Devsize size; union { struct { /* disk, (l)worm in j.j, sides */ int ctrl; /* disks only */ int targ; int lun; /* not implemented in sd(3) */ int mapped; char* file; /* ordinary file or dir instead */ int fd; char* sddir; /* /dev/sdXX name, for juke drives */ char* sddata; /* /dev/sdXX/data or other file */ } wren; struct { /* mcat mlev mirror */ Device* first; Device* last; int ndev; } cat; struct { /* cw */ Device* c; /* cache device */ Device* w; /* worm device */ Device* ro; /* dump - readonly */ } cw; struct { /* juke */ Device* j; /* (robotics, worm drives) - wrens */ Device* m; /* (sides) - r or l devices */ } j; struct { /* ro */ Device* parent; } ro; struct { /* fworm */ Device* fw; } fw; struct { /* part */ Device* d; long base; /* percentages */ long size; } part; struct { /* byte-swapped */ Device* d; } swab; }; }; typedef struct Sidestarts { Devsize sstart; /* blocks before start of side */ Devsize s1start; /* blocks before start of next side */ } Sidestarts; union Rabuf { struct { Device* dev; Off addr; }; Rabuf* link; }; struct Hiob { Iobuf* link; Lock; }; /* a 9P connection */ struct Chan { char type; /* major driver type i.e. Dev* */ int (*protocol)(Msgbuf*); /* version */ int msize; /* version */ char whochan[50]; char whoname[NAMELEN]; void (*whoprint)(Chan*); ulong flags; int chan; /* overall channel #, mostly for printing */ int nmsgs; /* outstanding messages, set under flock -- for flush */ Timet whotime; int nfile; /* used by cmd_files */ RWLock reflock; Chan* next; /* link list of chans */ Queue* send; Queue* reply; uchar authinfo[64]; void* pdata; /* sometimes is a Netconn* */ }; struct Filsys { char* name; /* name of filsys */ char* conf; /* symbolic configuration */ Device* dev; /* device that filsys is on */ int flags; #define FREAM (1<<0) /* mkfs */ #define FRECOVER (1<<1) /* install last dump */ #define FEDIT (1<<2) /* modified */ }; struct Startsb { char* name; Off startsb; }; struct Time { Timet lasttoy; Timet offset; }; /* * array of qids that are locked */ struct Tlock { Device* dev; Timet time; Off qpath; File* file; }; struct Cons { ulong flags; /* overall flags for all channels */ QLock; /* generic qlock for mutex */ int uid; /* botch -- used to get uid on cons_create */ int gid; /* botch -- used to get gid on cons_create */ int nuid; /* number of uids */ int ngid; /* number of gids */ Off offset; /* used to read files, c.f. fchar */ int chano; /* generator for channel numbers */ Chan* chan; /* console channel */ Filsys* curfs; /* current filesystem */ int profile; /* are we profiling? */ long* profbuf; ulong minpc; ulong maxpc; ulong nprofbuf; long nlarge; /* number of large message buffers */ long nsmall; /* ... small ... */ long nwormre; /* worm read errors */ long nwormwe; /* worm write errors */ long nwormhit; /* worm read cache hits */ long nwormmiss; /* worm read cache non-hits */ int noage; /* dont update cache age, dump and check */ long nwrenre; /* disk read errors */ long nwrenwe; /* disk write errors */ long nreseq; /* cache bucket resequence */ // Filter work[3]; /* thruput in messages */ // Filter rate[3]; /* thruput in bytes */ // Filter bhit[3]; /* getbufs that hit */ // Filter bread[3]; /* getbufs that miss and read */ // Filter brahead[3]; /* messages to readahead */ // Filter binit[3]; /* getbufs that miss and dont read */ }; struct File { QLock; Qid qid; Wpath* wpath; Chan* cp; /* null means a free slot */ Tlock* tlock; /* if file is locked */ File* next; /* in cp->flist */ Filsys* fs; Off addr; long slot; /* ordinal # of Dentry with a directory block */ Off lastra; /* read ahead address */ ulong fid; Userid uid; Auth *auth; char open; #define FREAD 1 #define FWRITE 2 #define FREMOV 4 Off doffset; /* directory reading */ ulong dvers; long dslot; }; struct Wpath { Wpath* up; /* pointer upwards in path */ Off addr; /* directory entry addr */ long slot; /* directory entry slot */ short refs; /* number of files using this structure */ }; struct Iobuf { QLock; Device* dev; Iobuf* fore; /* for lru */ Iobuf* back; /* for lru */ char* iobuf; /* only active while locked */ char* xiobuf; /* "real" buffer pointer */ Off addr; int flags; }; struct Uid { Userid uid; /* user id */ Userid lead; /* leader of group */ Userid *gtab; /* group table */ int ngrp; /* number of group entries */ char name[NAMELEN]; /* user name */ }; /* DONT TOUCH, this is the disk structure */ struct Fbuf { Off nfree; Off free[FEPERBUF]; }; /* DONT TOUCH, this is the disk structure */ struct Superb { Fbuf fbuf; Super1; }; struct Conf { ulong nmach; /* processors */ ulong mem; /* total physical bytes of memory */ ulong nuid; /* distinct uids */ ulong nserve; /* server processes */ ulong nfile; /* number of fid -- system wide */ ulong nwpath; /* number of active paths, derived from nfile */ ulong gidspace; /* space for gid names -- derived from nuid */ ulong nlgmsg; /* number of large message buffers */ ulong nsmmsg; /* number of small message buffers */ Off recovcw; /* recover addresses */ Off recovro; Off firstsb; Off recovsb; ulong configfirst; /* configure before starting normal operation */ char *confdev; char *devmap; /* name of config->file device mapping file */ ulong nauth; /* number of Auth structs */ uchar nodump; /* no periodic dumps */ uchar dumpreread; /* read and compare in dump copy */ }; enum { Mbmagic = 0xb0ffe3, }; /* * message buffers * 2 types, large and small */ struct Msgbuf { ulong magic; short count; short flags; #define LARGE (1<<0) #define FREE (1<<1) #define BFREE (1<<2) #define BTRACE (1<<7) Chan* chan; /* file server conn within a net. conn */ Msgbuf* next; uintptr param; /* misc. use; keep Conn* here */ int category; uchar* data; /* rp or wp: current processing point */ uchar* xdata; /* base of allocation */ }; /* * message buffer categories */ enum { Mxxx = 0, Mbeth1, Mbreply1, Mbreply2, Mbreply3, Mbreply4, MAXCAT, }; enum { PRINTSIZE = 256 }; struct { Lock; int machs; int exiting; } active; struct Command { char* arg0; char* help; void (*func)(int, char*[]); }; struct Flag { char* arg0; char* help; ulong flag; }; struct Rtc { int sec; int min; int hour; int mday; int mon; int year; }; typedef struct { /* constants during a given truncation */ Dentry *d; Iobuf *p; /* the block containing *d */ int uid; Off newsize; Off lastblk; /* last data block of file to keep */ /* variables */ Off relblk; /* # of current data blk within file */ int pastlast; /* have we walked past lastblk? */ int err; } Truncstate; /* * cw device */ /* DONT TOUCH, this is the disk structure */ struct Cache { Off maddr; /* cache map addr */ Off msize; /* cache map size in buckets */ Off caddr; /* cache addr */ Off csize; /* cache size */ Off fsize; /* current size of worm */ Off wsize; /* max size of the worm */ Off wmax; /* highwater write */ Off sbaddr; /* super block addr */ Off cwraddr; /* cw root addr */ Off roraddr; /* dump root addr */ Timet toytime; /* somewhere convienent */ Timet time; }; /* DONT TOUCH, this is the disk structure */ struct Bucket { long agegen; /* generator for ages in this bkt */ Centry entry[CEPERBK]; }; /* DONT TOUCH, this is in disk structures */ enum { Labmagic = 0xfeedfacedeadbeefULL, }; /* DONT TOUCH, this is the disk structure */ typedef struct Label Label; struct Label /* label block on Devlworms, in last block */ { uvlong magic; ushort ord; /* side number within Juke */ char service[64]; /* documentation only */ }; typedef struct Map Map; struct Map { char *from; Device *fdev; char *to; Device *tdev; Map *next; }; /* * scsi i/o */ enum { SCSIread = 0, SCSIwrite = 1, }; /* * Process states */ enum { Dead = 0, Moribund, Zombie, Ready, Scheding, Running, Queueing, Sending, Recving, MMUing, Exiting, Inwait, Wakeme, Broken, }; /* * devnone block numbers */ enum { Cwio1 = 1, Cwio2, Cwxx1, Cwxx2, Cwxx3, Cwxx4, Cwdump1, Cwdump2, Cuidbuf, Cckbuf, }; /* * error codes generated from the file server */ enum { Ebadspc = 1, Efid, Echar, Eopen, Ecount, Ealloc, Eqid, Eaccess, Eentry, Emode, Edir1, Edir2, Ephase, Eexist, Edot, Eempty, Ebadu, Enoattach, Ewstatb, Ewstatd, Ewstatg, Ewstatl, Ewstatm, Ewstato, Ewstatp, Ewstatq, Ewstatu, Ewstatv, Ename, Ewalk, Eronly, Efull, Eoffset, Elocked, Ebroken, Eauth, Eauth2, Efidinuse, Etoolong, Econvert, Eversion, Eauthdisabled, Eauthnone, Eauthfile, Eedge, MAXERR }; /* * device types */ enum { Devnone = 0, Devcon, /* console */ Devwren, /* disk drive */ Devworm, /* scsi optical drive */ Devlworm, /* scsi optical drive (labeled) */ Devfworm, /* fake read-only device */ Devjuke, /* scsi jukebox */ Devcw, /* cache with worm */ Devro, /* readonly worm */ Devmcat, /* multiple cat devices */ Devmlev, /* multiple interleave devices */ Devnet, /* network connection */ Devpart, /* partition */ Devfloppy, /* floppy drive */ Devswab, /* swab data between mem and device */ Devmirr, /* mirror devices */ MAXDEV }; /* * tags on block */ /* DONT TOUCH, this is in disk structures */ /* also, the order from Tdir to Tmaxind is exploited in indirck() & isdirty() */ enum { Tnone = 0, Tsuper, /* the super block */ #ifdef COMPAT32 Tdir, /* directory contents */ Tind1, /* points to blocks */ Tind2, /* points to Tind1 */ #else Tdirold, Tind1old, Tind2old, #endif Tfile, /* file contents; also defined in disk.h */ Tfree, /* in free list */ Tbuck, /* cache fs bucket */ Tvirgo, /* fake worm virgin bits */ Tcache, /* cw cache things */ Tconfig, /* configuration block */ #ifndef COMPAT32 /* Tdir & indirect blocks are last, to allow for greater depth */ Tdir, /* directory contents */ Tind1, /* points to blocks */ Tind2, /* points to Tind1 */ Tind3, /* points to Tind2 */ Tind4, /* points to Tind3 */ Maxtind, #endif /* gap for more indirect block depth in future */ Tlabel = 32, /* Devlworm label in last block */ MAXTAG, #ifdef COMPAT32 Tmaxind = Tind2, #else Tmaxind = Maxtind - 1, #endif }; /* * flags to getbuf */ enum { Brd = (1<<0), /* read the block if miss */ Bprobe = (1<<1), /* return null if miss */ Bmod = (1<<2), /* buffer is dirty, needs writing */ Bimm = (1<<3), /* write immediately on putbuf */ Bres = (1<<4), /* reserved, never renamed */ }; Conf conf; Cons cons; #pragma varargck type "Z" Device* #pragma varargck type "T" Timet #pragma varargck type "I" uchar* #pragma varargck type "E" uchar* #pragma varargck type "G" int extern char *annstrs[]; extern Biobuf bin; extern Map *devmap; extern int (*fsprotocol[])(Msgbuf*);