ref: 7038b412045ad003366804789e7fecaf0552f77c
dir: /dat.h/
typedef signed char s8; typedef signed short s16; typedef signed int s32; typedef signed long long s64; typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; typedef struct Config Config; typedef struct Data Data; typedef struct Dentryhdr Dentryhdr; typedef struct Dentry Dentry; typedef struct Datahdr Datahdr; typedef struct Indirect Indirect; typedef struct Name Name; typedef struct Super Super; typedef struct Tlock Tlock; typedef struct User User; typedef struct Aux Aux; enum { KiB = 1024ULL, /* Kibibytes */ MiB = KiB*KiB, /* Mibibytes */ GiB = KiB*MiB, /* Gibibytes */ TiB = KiB*GiB, /* Tibibytes */ Ngroups = 32, /* maximum number of groups an user can belong to */ None = 0, /* user ID for "none" */ Noworld = 9999, /* conventional id for "noworld" group */ Userlen = 32, Servicelen = 128, Nfirst = 6, /* length of name stored in Name */ Nsec = 1000ULL*1000*1000, Usec = 1000ULL*1000, Msec = 1000ULL, Nbkp = 1, Nrefresh = 3*Nsec, /* for Dentry.flags and Data.flags */ Fsys = 0x80,/* for flagging .n, .nl and .nle files. Dentry.flags */ Fn = 1, /* .n Name index file format */ Fe = 2, /* Binary extents file format. TODO we are using text extents now */ In = 0, /* reli of .n file */ Inl = 1, /* reli of .nl file */ Inle= 2, /* reli of .nle file */ Nsys, }; /* * fundamental constants and types of the implementation * changing any of these changes the layout on disk * The very first block (index = 0) has the magic written at offset 256. * * Trying to keep the Qpath the same as the directory entry block number * for the system files to help me identify numbers easily. * * derived constants * Nindperblock number of block pointers in a block */ enum { Blocksize = 512ULL, /* minimum data unit size */ Maxdatablockunits = 2048, Nindperblock= (Blocksize-3*sizeof(u64))/sizeof(u64),/* number of pointers per block */ Nu64perblock= (Blocksize/sizeof(u64)), /* number of u64's in a block */ Dpathidx = (Blocksize/sizeof(u64) -1), /* index of path in the last data block, last u64 */ Ndblock = 46, /* number of direct blocks in a Dentry */ Niblock = 5, /* maximum depth of indirect blocks, can increase it to 9 without issues */ /* global block numbers. The bkp contents locations are calculated by ream() */ Bdmagic = 0, /* block number of first block. Bmagic conflicts with bio.h */ Bdconfig= 1, /* block number of /a/config dentry and contents */ Bdsuper = 2, /* block number of /a/super dentry and contents */ Bda = 3, /* block number of /a directory */ Bdanames= 4, /* block number of /a dir names directory */ Bdalnames= 5, /* block number of /a dir long names directory */ Bdalnamesextents= 6, /* block number of /a dir long names extents directory */ Bdusers = 7, /* block number of /a/users/ directory entry */ Bdusersnames= 8,/* block number of /a/users/ directory names */ Bduserslnames= 9,/* block number of /a/users/ directory long names */ Bduserslnamesextents= 10,/* block number of /a/users/ directory long names extents */ /* contents of blocks below change on use */ Bdbkp = 11, /* block number of /a/bkp directory */ Bdbkpnames= 12, /* block number of /a/bkp directory names */ Bdbkplnames= 13,/* block number of /a/bkp directory long names */ Bdbkplnamesextents= 14, /* block number of /a/bkp directory long names extents */ Bdusersinuse = 15, /* block number of /a/users/inuse dentry and contents */ Bdfrees = 16, /* block number of /a/frees dentry, text file of free extents */ /* no user writes allowed on blocks below Bdctl */ Bdctl = 17, /* block number of /a/ctl dentry, empty contents, virtual file */ Bdusersstaging = 18,/* block number of /a/users/staging dentry */ Bdroot = 19, /* block number of root directory */ Bdrootnames = 20, /* block number of root directory names */ Bdrootlnames = 21, /* block number of root directory long names */ Bdrootlnamesextents = 22, /* block number of root directory long names extents */ Nbused, /* blocks used up by default */ /* number of blocks used by the above and the backup blocks */ Nminblocks = Nbused+(Nbkp*3), /* Qpnone is the Tag.path of free blocks/extents(Tfree), and zero'ed out dentry blocks */ Qpnone = 0, Qpconfig = Bdconfig, /* /a/config block Tag.qpath */ Qpsuper = Bdsuper, /* /a/super block Tag.qpath */ Qpa = Bda, /* /a */ Qpanames = Bdanames, /* /a */ Qpalnames = Bdalnames, /* /a */ Qpalnamesextents= Bdalnamesextents, /* /a */ Qpusers = Bdusers, /* /a/users block Tag.qpath */ Qpusersnames= Bdusersnames, /* /a/users block Tag.qpath */ Qpuserslnames= Bduserslnames, /* /a/users block Tag.qpath */ Qpuserslnamesextents= Bduserslnamesextents, /* /a/users block Tag.qpath */ Qpbkp = Bdbkp, /* /a/bkp block Tag.qpath */ Qpbkpnames = Bdbkpnames, /* /a/bkp block Tag.qpath */ Qpbkplnames = Bdbkplnames, /* /a/bkp block Tag.qpath */ Qpbkplnamesextents= Bdbkplnamesextents, /* /a/bkp block Tag.qpath */ Qpusersinuse= Bdusersinuse, /* /a/users/inuse block Tag.qpath */ Qpfrees = Bdfrees, /* /a/frees block Tag.qpath */ /* system qpaths */ Qpmagic = Bdrootlnamesextents+1, /* magic block Tag.qpath, could use Bdroot butt this avoids confusion by keeping the block numbers and qpaths distinct */ Qpconfig0, /* /a/bkp/config.0 block Tag.qpath */ Qpsuper0, /* /a/bkp/super.0 block Tag.qpath */ Qproot0, /* /a/bkp/root.0 block Tag.qpath */ Qproot = 32, /* /, so fscreate() and fswrite() can disallow any create's below */ Qprootnames, Qprootlnames, Qprootlnamesextents, Qpctl, /* /a/ctl */ Qpusersstaging, /* /a/users/staging block Tag.qpath */ Nqidgen = 64, /* check qpath for overflows - TODO, should be 2^64 */ Maxqpath = 72057594037927936ULL, /* 2^56 */ Nthdirty = 9, /* dirty byte is the 9th byte in the Tag */ }; #pragma pack on /* DONT TOUCH, this is the disk structure */ /* no access time */ struct Dentryhdr { u8 tag; u8 flags; /* attributes (names extents, names - hide system files) */ s16 uid; s16 gid; s16 muid; /* 8 */ u64 size; /* 0 for directories. For files, size in bytes of the content - 16 */ u64 pdblkno; /* block number of the parent directory entry. 0 for root. - 24 */ u64 pqpath; /* parent qid.path - 32 */ u64 preli; /* my reli in my parent's directory entry - 40 */ u64 mtime; /* modified time in nano seconds from epoch - 48 */ u64 qpath; /* unique identifier Qid.path 56 */ u32 version; /* Qid.version 60 */ u32 mode; /* same bits as defined in /sys/include/libc.h:/Dir\.mode/ - 64 */ }; struct Datahdr { u8 tag; u8 flags; /* 0 for text, 1 for In Name file, 2 for extents */ u16 len; u64 dblkno; /* block number of the directory entry */ }; #pragma pack off enum { /* size of identifiers used in a Tdata block */ Ddataidssize = sizeof(Datahdr) +sizeof(u64 /* trailing path */), /* max possible size of data that can be stuffed into a Dentry */ Ddatasize = Blocksize -sizeof(Dentryhdr) -sizeof(u64 /* trailing path */), Maxdatablocksize = Maxdatablockunits*Blocksize -Ddataidssize, }; #pragma pack on /* DONT TOUCH, these are all disk structures */ struct Super { u64 qidgen; /* generator for unique ids. starts from 1024. */ u64 fsok; /* fsck status, using 64 bits to keep it all aligned */ }; struct Dentry { Dentryhdr; union { struct { u64 dblocks[Ndblock]; /* direct blocks. */ /* List of Tdata block numbers for files and Tdentry block numbers for directories */ u64 iblocks[Niblock]; /* indirect blocks */ }; Super; /* when size <= Ddatasize, store the data here itself */ s8 buf[Ddatasize]; }; u64 path; /* same as qid.path */ }; struct Indirect { u8 tagi; /* the suffix i to avoid union complaining about ambiguous fields */ u8 pad[7]; /* unused, to align to a multiple of 8 */ u64 dblkno; /* block number of the directory entry */ u64 bufa[Nindperblock]; u64 pathi; /* same as qid.path */ }; struct Data /* used to unmarshall the disk contents */ { Datahdr; u8 buf[1]; /* upto Maxdatablocksize, followed by u64 qid.path */ /* u64 path; same as qid.path at the end of the data content - check consistency */ }; struct Name { u16 namelen; s8 name[Nfirst]; /* first 6 bytes. If longer, use noffset */ u64 noffset; /* offset where the name is stored in .nl - long names file */ }; #pragma pack off /* * array of qids that are locked */ struct Tlock { u64 time; u64 qpath; u64 dblkno; Tlock *prev, *next; }; struct Aux { u64 dblkno; /* directory entry absolute block number */ u64 pdblkno;/* block number of my parent's directory entry */ u64 pqpath;/* block number of my parent's directory entry */ u64 preli; /* my relative index in the parent's directory entry */ u8 flags; /* corresponds to Dentry.flags and Data.flags */ u16 uid; u8 tlocked; /* for exclusive use files, flag to indicate lock */ u64 dri; /* directory index while reading a directory */ s8 *ctlmsg; u32 nctlmsg; /* u64 lastreadahead; TODO */ }; /* every user is also a group with one user. */ struct User { s16 id; /* user id */ s16 lid; /* id of the leader of group */ char name[Userlen]; /* user name */ s16 *members;/* list of member id's belonging to this group */ int nmembers;/* number of members in this group */ int nalloc; /* allocated space members */ User *prev, *next; /* linked list sorted by id */ }; /* storing this in ascii to the Bdconfig block */ struct Bkp { u64 srcbno; /* source of the backup */ u64 dest[Nbkp]; /* destinations written to */ }; struct Config { u64 size; /* size from dirfstat */ u64 nblocks; /* size in blocks */ struct Bkp config; struct Bkp super; struct Bkp root; char service[Servicelen]; }; enum { Nworks = 1024, /* make this a parameter? */ Nworkers = 32, /* make this a parameter? */ Nuserserrmsg = 64, }; /* * error codes generated from the file server */ enum { Eaccess = 1, Ealloc, Eauth, Eauthmsg, Ebadname, Ebadspc, Ebadu, Ebroken, Echar, Econvert, Ecount, Edexist, Edir1, Edir2, Edirty, Edot, Eempty, Eentry, Eexist, Efid, Efidinuse, Efull, Einval, Einvread, Einvwrite, Einvusers, Elocked, Emode, Ename, Enomem, Enotd, Enotdir, Enotfound, Enotg, Enotl, Enotm, Enotu, Enotw, Enouser, Enousers, Eoffset, Eopen, Eperm, Ephase, Eqid, Eqidmode, Eronly, Ersc, Eshutdown, Esystem, Etoolong, Ewalk, MAXERR }; /* * tags on block */ /* DONT TOUCH, this is in disk structures */ /* the first 512 bytes holds the magic. Not bothering with a tag for 1 Unit. Use Tdentry for that. */ /* also, the order from Tdata to Tmaxind is exploited in indirck() & isdirty() */ enum { Tblank = 0, Tfree = 0, /* free block */ Tnone = 0, Tdata, /* actual file contents */ Tdentry, /* directory entry, size = Dentrysize */ /* Tdata & indirect blocks are last, to allow for greater depth */ Tind0, /* contains a list of Tdata block numbers for files and Tdentry block numbers for directories.*/ Tind1, /* contains a list of Tind0 block numbers */ Tind2, /* contains a list of Tind1 block numbers */ Tind3, /* contains a list of Tind1 block numbers */ Tind4, /* contains a list of Tind1 block numbers */ /* gap for more indirect block depth in future. It can be put upto Tind7 without needing any code changes */ Maxtind, /* should be Tind0+Niblock */ MAXTAG = Maxtind, Tmaxind = Maxtind - 1, }; /* * flags to getbuf */ enum { Breadonly = 1,/* read the block, cannot write to it */ Bwritable = 0, Bfreshalloc = 1,/* newly allocated block, no contents on the disk */ Bused = 0,/* has contents on the disk */ }; #define SECOND(n) (n) #define MINUTE(n) (n*SECOND(60)) #define HOUR(n) (n*MINUTE(60)) #define DAY(n) (n*HOUR(24)) #define TLOCK MINUTE(5) extern char* errstring[MAXERR]; extern char service[Servicelen]; extern char *tagnames[]; extern char *devfile; /* device file path */ extern int devfd ; /* device fd */ extern int writeallow; extern int wstatallow; extern int allownone; extern u8 readonly; extern u8 shuttingdown; extern u8 noauth; /* used by panic() */ extern char *procname; extern Config config; extern char userserrmsg[Nuserserrmsg]; Config *parseconfig(s8 *cfg, Config *c); typedef struct Errenv Errenv; struct Errenv /* Error environment */ { jmp_buf label[16]; u8 nlabel; }; extern s8 err[ERRMAX]; extern Errenv **envpp; void nexterror(void); void error(s8 *fmt, ...); extern void showerrenv(char *msg); #define poperror() (*envpp)->nlabel-- /* #define waserror() (showerrenv("waserror before\n"), (*envpp)->nlabel++, setjmp((*envpp)->label[(*envpp)->nlabel-1])) */ #define waserror() ((*envpp)->nlabel++, setjmp((*envpp)->label[(*envpp)->nlabel-1]))