15e96a66cSDavid du Colombier typedef struct Arch Arch; 25e96a66cSDavid du Colombier typedef struct BList BList; 35e96a66cSDavid du Colombier typedef struct Block Block; 45e96a66cSDavid du Colombier typedef struct Cache Cache; 55e96a66cSDavid du Colombier typedef struct Disk Disk; 65e96a66cSDavid du Colombier typedef struct Entry Entry; 7e569ccb5SDavid du Colombier typedef struct Fsck Fsck; 85e96a66cSDavid du Colombier typedef struct Header Header; 95e96a66cSDavid du Colombier typedef struct Label Label; 105e96a66cSDavid du Colombier typedef struct Periodic Periodic; 115e96a66cSDavid du Colombier typedef struct Snap Snap; 125e96a66cSDavid du Colombier typedef struct Source Source; 135e96a66cSDavid du Colombier typedef struct Super Super; 145e96a66cSDavid du Colombier typedef struct WalkPtr WalkPtr; 155e96a66cSDavid du Colombier 1612fd1c83SDavid du Colombier #pragma incomplete Arch 1712fd1c83SDavid du Colombier #pragma incomplete BList 1812fd1c83SDavid du Colombier #pragma incomplete Cache 1912fd1c83SDavid du Colombier #pragma incomplete Disk 2012fd1c83SDavid du Colombier #pragma incomplete Periodic 2112fd1c83SDavid du Colombier #pragma incomplete Snap 2212fd1c83SDavid du Colombier 2300580da5SDavid du Colombier /* tunable parameters - probably should not be constants */ 245e96a66cSDavid du Colombier enum { 2500580da5SDavid du Colombier /* 2600580da5SDavid du Colombier * estimate of bytes per dir entries - determines number 2700580da5SDavid du Colombier * of index entries in the block 2800580da5SDavid du Colombier */ 2900580da5SDavid du Colombier BytesPerEntry = 100, 3000580da5SDavid du Colombier /* don't allocate in block if more than this percentage full */ 3100580da5SDavid du Colombier FullPercentage = 80, 325e96a66cSDavid du Colombier FlushSize = 200, /* number of blocks to flush */ 335e96a66cSDavid du Colombier DirtyPercentage = 50, /* maximum percentage of dirty blocks */ 345e96a66cSDavid du Colombier }; 355e96a66cSDavid du Colombier 365e96a66cSDavid du Colombier enum { 375e96a66cSDavid du Colombier NilBlock = (~0UL), 385e96a66cSDavid du Colombier MaxBlock = (1UL<<31), 395e96a66cSDavid du Colombier }; 405e96a66cSDavid du Colombier 415e96a66cSDavid du Colombier enum { 425e96a66cSDavid du Colombier HeaderMagic = 0x3776ae89, 435e96a66cSDavid du Colombier HeaderVersion = 1, 445e96a66cSDavid du Colombier HeaderOffset = 128*1024, 455e96a66cSDavid du Colombier HeaderSize = 512, 465e96a66cSDavid du Colombier SuperMagic = 0x2340a3b1, 475e96a66cSDavid du Colombier SuperSize = 512, 485e96a66cSDavid du Colombier SuperVersion = 1, 495e96a66cSDavid du Colombier LabelSize = 14, 505e96a66cSDavid du Colombier }; 515e96a66cSDavid du Colombier 525e96a66cSDavid du Colombier /* well known tags */ 535e96a66cSDavid du Colombier enum { 545e96a66cSDavid du Colombier BadTag = 0, /* this tag should not be used */ 555e96a66cSDavid du Colombier RootTag = 1, /* root of fs */ 565e96a66cSDavid du Colombier EnumTag, /* root of a dir listing */ 575e96a66cSDavid du Colombier UserTag = 32, /* all other tags should be >= UserTag */ 585e96a66cSDavid du Colombier }; 595e96a66cSDavid du Colombier 605e96a66cSDavid du Colombier struct Super { 615e96a66cSDavid du Colombier u16int version; 625e96a66cSDavid du Colombier u32int epochLow; 635e96a66cSDavid du Colombier u32int epochHigh; 645e96a66cSDavid du Colombier u64int qid; /* next qid */ 655e96a66cSDavid du Colombier u32int active; /* root of active file system */ 665e96a66cSDavid du Colombier u32int next; /* root of next snapshot to archive */ 675e96a66cSDavid du Colombier u32int current; /* root of snapshot currently archiving */ 685e96a66cSDavid du Colombier uchar last[VtScoreSize]; /* last snapshot successfully archived */ 695e96a66cSDavid du Colombier char name[128]; /* label */ 705e96a66cSDavid du Colombier }; 715e96a66cSDavid du Colombier 725e96a66cSDavid du Colombier 735e96a66cSDavid du Colombier struct Fs { 745e96a66cSDavid du Colombier Arch *arch; /* immutable */ 755e96a66cSDavid du Colombier Cache *cache; /* immutable */ 765e96a66cSDavid du Colombier int mode; /* immutable */ 775e96a66cSDavid du Colombier int blockSize; /* immutable */ 785e96a66cSDavid du Colombier VtSession *z; /* immutable */ 795e96a66cSDavid du Colombier Snap *snap; /* immutable */ 80*0c6300e7SDavid du Colombier /* immutable; copy here & Fsys to ease error reporting */ 81*0c6300e7SDavid du Colombier char *name; 825e96a66cSDavid du Colombier 835e96a66cSDavid du Colombier Periodic *metaFlush; /* periodically flushes metadata cached in files */ 845e96a66cSDavid du Colombier 855e96a66cSDavid du Colombier /* 865e96a66cSDavid du Colombier * epoch lock. 875e96a66cSDavid du Colombier * Most operations on the fs require a read lock of elk, ensuring that 885e96a66cSDavid du Colombier * the current high and low epochs do not change under foot. 895e96a66cSDavid du Colombier * This lock is mostly acquired via a call to fileLock or fileRlock. 905e96a66cSDavid du Colombier * Deletion and creation of snapshots occurs under a write lock of elk, 915e96a66cSDavid du Colombier * ensuring no file operations are occurring concurrently. 925e96a66cSDavid du Colombier */ 935e96a66cSDavid du Colombier VtLock *elk; /* epoch lock */ 945e96a66cSDavid du Colombier u32int ehi; /* epoch high */ 955e96a66cSDavid du Colombier u32int elo; /* epoch low */ 965e96a66cSDavid du Colombier 9781cf8742SDavid du Colombier int halted; /* epoch lock is held to halt (console initiated) */ 9881cf8742SDavid du Colombier 995e96a66cSDavid du Colombier Source *source; /* immutable: root of sources */ 1005e96a66cSDavid du Colombier File *file; /* immutable: root of files */ 1015e96a66cSDavid du Colombier }; 1025e96a66cSDavid du Colombier 1035e96a66cSDavid du Colombier /* 1045e96a66cSDavid du Colombier * variant on VtEntry 1055e96a66cSDavid du Colombier * there are extra fields when stored locally 1065e96a66cSDavid du Colombier */ 1075e96a66cSDavid du Colombier struct Entry { 1085e96a66cSDavid du Colombier u32int gen; /* generation number */ 1095e96a66cSDavid du Colombier ushort psize; /* pointer block size */ 1105e96a66cSDavid du Colombier ushort dsize; /* data block size */ 1115e96a66cSDavid du Colombier uchar depth; /* unpacked from flags */ 1125e96a66cSDavid du Colombier uchar flags; 1135e96a66cSDavid du Colombier uvlong size; 1145e96a66cSDavid du Colombier uchar score[VtScoreSize]; 1155e96a66cSDavid du Colombier u32int tag; /* tag for local blocks: zero if stored on Venti */ 11600580da5SDavid du Colombier u32int snap; /* non-zero -> entering snapshot of given epoch */ 1175e96a66cSDavid du Colombier uchar archive; /* archive this snapshot: only valid for snap != 0 */ 1185e96a66cSDavid du Colombier }; 1195e96a66cSDavid du Colombier 12000580da5SDavid du Colombier /* 12100580da5SDavid du Colombier * This is called a `stream' in the fossil paper. There used to be Sinks too. 12200580da5SDavid du Colombier * We believe that Sources and Files are one-to-one. 12300580da5SDavid du Colombier */ 1245e96a66cSDavid du Colombier struct Source { 1255e96a66cSDavid du Colombier Fs *fs; /* immutable */ 1265e96a66cSDavid du Colombier int mode; /* immutable */ 12757195852SDavid du Colombier int issnapshot; /* immutable */ 1285e96a66cSDavid du Colombier u32int gen; /* immutable */ 1295e96a66cSDavid du Colombier int dsize; /* immutable */ 1305e96a66cSDavid du Colombier int dir; /* immutable */ 1315e96a66cSDavid du Colombier 1325e96a66cSDavid du Colombier Source *parent; /* immutable */ 133*0c6300e7SDavid du Colombier File *file; /* immutable; point back */ 1345e96a66cSDavid du Colombier 1355e96a66cSDavid du Colombier VtLock *lk; 1365e96a66cSDavid du Colombier int ref; 1375e96a66cSDavid du Colombier /* 1385e96a66cSDavid du Colombier * epoch for the source 1395e96a66cSDavid du Colombier * for ReadWrite sources, epoch is used to lazily notice 1405e96a66cSDavid du Colombier * sources that must be split from the snapshots. 1415e96a66cSDavid du Colombier * for ReadOnly sources, the epoch represents the minimum epoch 1425e96a66cSDavid du Colombier * along the chain from the root, and is used to lazily notice 1435e96a66cSDavid du Colombier * sources that have become invalid because they belong to an old 1445e96a66cSDavid du Colombier * snapshot. 1455e96a66cSDavid du Colombier */ 1465e96a66cSDavid du Colombier u32int epoch; 1475e96a66cSDavid du Colombier Block *b; /* block containing this source */ 1485e96a66cSDavid du Colombier uchar score[VtScoreSize]; /* score of block containing this source */ 1495e96a66cSDavid du Colombier u32int scoreEpoch; /* epoch of block containing this source */ 1505e96a66cSDavid du Colombier int epb; /* immutable: entries per block in parent */ 1515e96a66cSDavid du Colombier u32int tag; /* immutable: tag of parent */ 1525e96a66cSDavid du Colombier u32int offset; /* immutable: entry offset in parent */ 1535e96a66cSDavid du Colombier }; 1545e96a66cSDavid du Colombier 1555e96a66cSDavid du Colombier 1565e96a66cSDavid du Colombier struct Header { 1575e96a66cSDavid du Colombier ushort version; 1585e96a66cSDavid du Colombier ushort blockSize; 1595e96a66cSDavid du Colombier ulong super; /* super blocks */ 1605e96a66cSDavid du Colombier ulong label; /* start of labels */ 1615e96a66cSDavid du Colombier ulong data; /* end of labels - start of data blocks */ 1625e96a66cSDavid du Colombier ulong end; /* end of data blocks */ 1635e96a66cSDavid du Colombier }; 1645e96a66cSDavid du Colombier 1655e96a66cSDavid du Colombier /* 1665e96a66cSDavid du Colombier * contains a one block buffer 1675e96a66cSDavid du Colombier * to avoid problems of the block changing underfoot 1685e96a66cSDavid du Colombier * and to enable an interface that supports unget. 1695e96a66cSDavid du Colombier */ 1705e96a66cSDavid du Colombier struct DirEntryEnum { 1715e96a66cSDavid du Colombier File *file; 1725e96a66cSDavid du Colombier 1735e96a66cSDavid du Colombier u32int boff; /* block offset */ 1745e96a66cSDavid du Colombier 1755e96a66cSDavid du Colombier int i, n; 1765e96a66cSDavid du Colombier DirEntry *buf; 1775e96a66cSDavid du Colombier }; 1785e96a66cSDavid du Colombier 179e569ccb5SDavid du Colombier /* Block states */ 1805e96a66cSDavid du Colombier enum { 1815e96a66cSDavid du Colombier BsFree = 0, /* available for allocation */ 1825e96a66cSDavid du Colombier BsBad = 0xFF, /* something is wrong with this block */ 1835e96a66cSDavid du Colombier 1845e96a66cSDavid du Colombier /* bit fields */ 1855e96a66cSDavid du Colombier BsAlloc = 1<<0, /* block is in use */ 186e569ccb5SDavid du Colombier BsCopied = 1<<1,/* block has been copied (usually in preparation for unlink) */ 1875e96a66cSDavid du Colombier BsVenti = 1<<2, /* block has been stored on Venti */ 188e569ccb5SDavid du Colombier BsClosed = 1<<3,/* block has been unlinked on disk from active file system */ 1895e96a66cSDavid du Colombier BsMask = BsAlloc|BsCopied|BsVenti|BsClosed, 1905e96a66cSDavid du Colombier }; 1915e96a66cSDavid du Colombier 1925e96a66cSDavid du Colombier /* 1935e96a66cSDavid du Colombier * block types 1945e96a66cSDavid du Colombier * more regular than Venti block types 1955e96a66cSDavid du Colombier * bit 3 -> block or data block 1965e96a66cSDavid du Colombier * bits 2-0 -> level of block 1975e96a66cSDavid du Colombier */ 1985e96a66cSDavid du Colombier enum { 1995e96a66cSDavid du Colombier BtData, 2005e96a66cSDavid du Colombier BtDir = 1<<3, 2015e96a66cSDavid du Colombier BtLevelMask = 7, 2025e96a66cSDavid du Colombier BtMax = 1<<4, 2035e96a66cSDavid du Colombier }; 2045e96a66cSDavid du Colombier 2055e96a66cSDavid du Colombier /* io states */ 2065e96a66cSDavid du Colombier enum { 2075e96a66cSDavid du Colombier BioEmpty, /* label & data are not valid */ 2085e96a66cSDavid du Colombier BioLabel, /* label is good */ 2095e96a66cSDavid du Colombier BioClean, /* data is on the disk */ 2105e96a66cSDavid du Colombier BioDirty, /* data is not yet on the disk */ 2115e96a66cSDavid du Colombier BioReading, /* in process of reading data */ 2125e96a66cSDavid du Colombier BioWriting, /* in process of writing data */ 2135e96a66cSDavid du Colombier BioReadError, /* error reading: assume disk always handles write errors */ 2145e96a66cSDavid du Colombier BioVentiError, /* error reading from venti (probably disconnected) */ 2155e96a66cSDavid du Colombier BioMax 2165e96a66cSDavid du Colombier }; 2175e96a66cSDavid du Colombier 2185e96a66cSDavid du Colombier struct Label { 2195e96a66cSDavid du Colombier uchar type; 2205e96a66cSDavid du Colombier uchar state; 2215e96a66cSDavid du Colombier u32int tag; 2225e96a66cSDavid du Colombier u32int epoch; 2235e96a66cSDavid du Colombier u32int epochClose; 2245e96a66cSDavid du Colombier }; 2255e96a66cSDavid du Colombier 2265e96a66cSDavid du Colombier struct Block { 2275e96a66cSDavid du Colombier Cache *c; 2285e96a66cSDavid du Colombier int ref; 2295e96a66cSDavid du Colombier int nlock; 23074f16c81SDavid du Colombier uintptr pc; /* pc that fetched this block from the cache */ 2315e96a66cSDavid du Colombier 2325e96a66cSDavid du Colombier VtLock *lk; 2335e96a66cSDavid du Colombier 2345e96a66cSDavid du Colombier int part; 2355e96a66cSDavid du Colombier u32int addr; 2365e96a66cSDavid du Colombier uchar score[VtScoreSize]; /* score */ 2375e96a66cSDavid du Colombier Label l; 2385e96a66cSDavid du Colombier 23961201b97SDavid du Colombier uchar *dmap; 24061201b97SDavid du Colombier 2415e96a66cSDavid du Colombier uchar *data; 2425e96a66cSDavid du Colombier 2435e96a66cSDavid du Colombier /* the following is private; used by cache */ 2445e96a66cSDavid du Colombier 2455e96a66cSDavid du Colombier Block *next; /* doubly linked hash chains */ 2465e96a66cSDavid du Colombier Block **prev; 2475e96a66cSDavid du Colombier u32int heap; /* index in heap table */ 2485e96a66cSDavid du Colombier u32int used; /* last reference times */ 2495e96a66cSDavid du Colombier 2505e96a66cSDavid du Colombier u32int vers; /* version of dirty flag */ 2515e96a66cSDavid du Colombier 2525e96a66cSDavid du Colombier BList *uhead; /* blocks to unlink when this block is written */ 2535e96a66cSDavid du Colombier BList *utail; 2545e96a66cSDavid du Colombier 2555e96a66cSDavid du Colombier /* block ordering for cache -> disk */ 2565e96a66cSDavid du Colombier BList *prior; /* list of blocks before this one */ 2575e96a66cSDavid du Colombier 2585e96a66cSDavid du Colombier Block *ionext; 2595e96a66cSDavid du Colombier int iostate; 2605e96a66cSDavid du Colombier VtRendez *ioready; 2615e96a66cSDavid du Colombier }; 2625e96a66cSDavid du Colombier 2635e96a66cSDavid du Colombier /* tree walker, for gc and archiver */ 2645e96a66cSDavid du Colombier struct WalkPtr 2655e96a66cSDavid du Colombier { 2665e96a66cSDavid du Colombier uchar *data; 2675e96a66cSDavid du Colombier int isEntry; 2685e96a66cSDavid du Colombier int n; 2695e96a66cSDavid du Colombier int m; 2705e96a66cSDavid du Colombier Entry e; 2715e96a66cSDavid du Colombier uchar type; 2725e96a66cSDavid du Colombier u32int tag; 2735e96a66cSDavid du Colombier }; 2745e96a66cSDavid du Colombier 275e569ccb5SDavid du Colombier enum 276e569ccb5SDavid du Colombier { 277e569ccb5SDavid du Colombier DoClose = 1<<0, 278e569ccb5SDavid du Colombier DoClre = 1<<1, 279e569ccb5SDavid du Colombier DoClri = 1<<2, 280e569ccb5SDavid du Colombier DoClrp = 1<<3, 281e569ccb5SDavid du Colombier }; 282e569ccb5SDavid du Colombier 283e569ccb5SDavid du Colombier struct Fsck 284e569ccb5SDavid du Colombier { 285e569ccb5SDavid du Colombier /* filled in by caller */ 286e569ccb5SDavid du Colombier int printblocks; 287e569ccb5SDavid du Colombier int useventi; 288e569ccb5SDavid du Colombier int flags; 289e569ccb5SDavid du Colombier int printdirs; 290e569ccb5SDavid du Colombier int printfiles; 291e569ccb5SDavid du Colombier int walksnapshots; 292e569ccb5SDavid du Colombier int walkfs; 293e569ccb5SDavid du Colombier Fs *fs; 294e569ccb5SDavid du Colombier int (*print)(char*, ...); 295e569ccb5SDavid du Colombier void (*clre)(Fsck*, Block*, int); 296e569ccb5SDavid du Colombier void (*clrp)(Fsck*, Block*, int); 297e569ccb5SDavid du Colombier void (*close)(Fsck*, Block*, u32int); 298e569ccb5SDavid du Colombier void (*clri)(Fsck*, char*, MetaBlock*, int, Block*); 299e569ccb5SDavid du Colombier 300e569ccb5SDavid du Colombier /* used internally */ 301e569ccb5SDavid du Colombier Cache *cache; 302e569ccb5SDavid du Colombier uchar *amap; /* all blocks seen so far */ 303e569ccb5SDavid du Colombier uchar *emap; /* all blocks seen in this epoch */ 304e569ccb5SDavid du Colombier uchar *xmap; /* all blocks in this epoch with parents in this epoch */ 305e569ccb5SDavid du Colombier uchar *errmap; /* blocks with errors */ 306e569ccb5SDavid du Colombier uchar *smap; /* walked sources */ 307e569ccb5SDavid du Colombier int nblocks; 308e569ccb5SDavid du Colombier int bsize; 309e569ccb5SDavid du Colombier int walkdepth; 310e569ccb5SDavid du Colombier u32int hint; /* where the next root probably is */ 311e569ccb5SDavid du Colombier int nseen; 312e569ccb5SDavid du Colombier int quantum; 313e569ccb5SDavid du Colombier int nclre; 314e569ccb5SDavid du Colombier int nclrp; 315e569ccb5SDavid du Colombier int nclose; 316e569ccb5SDavid du Colombier int nclri; 317e569ccb5SDavid du Colombier }; 318e569ccb5SDavid du Colombier 319f6333ca0SDavid du Colombier /* disk partitions; keep in sync with partname[] in disk.c */ 3205e96a66cSDavid du Colombier enum { 3215e96a66cSDavid du Colombier PartError, 3225e96a66cSDavid du Colombier PartSuper, 3235e96a66cSDavid du Colombier PartLabel, 3245e96a66cSDavid du Colombier PartData, 3255e96a66cSDavid du Colombier PartVenti, /* fake partition */ 3265e96a66cSDavid du Colombier }; 3275e96a66cSDavid du Colombier 3285e96a66cSDavid du Colombier extern vtType[BtMax]; 329