xref: /plan9/sys/src/cmd/fossil/dat.h (revision 81cf874224a4620dc66ce2d894718f8bb735f81d)
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;
75e96a66cSDavid du Colombier typedef struct Header Header;
85e96a66cSDavid du Colombier typedef struct Label Label;
95e96a66cSDavid du Colombier typedef struct Periodic Periodic;
105e96a66cSDavid du Colombier typedef struct Snap Snap;
115e96a66cSDavid du Colombier typedef struct Source Source;
125e96a66cSDavid du Colombier typedef struct Super Super;
135e96a66cSDavid du Colombier typedef struct WalkPtr WalkPtr;
145e96a66cSDavid du Colombier 
155e96a66cSDavid du Colombier /* tuneable parameters - probably should not be constants */
165e96a66cSDavid du Colombier enum {
175e96a66cSDavid du Colombier 	BytesPerEntry = 100,	/* estimate of bytes per dir entries - determines number of index entries in the block */
185e96a66cSDavid du Colombier 	FullPercentage = 80,	/* don't allocate in block if more than this percentage full */
195e96a66cSDavid du Colombier 	FlushSize = 200,	/* number of blocks to flush */
205e96a66cSDavid du Colombier 	DirtyPercentage = 50,	/* maximum percentage of dirty blocks */
215e96a66cSDavid du Colombier };
225e96a66cSDavid du Colombier 
235e96a66cSDavid du Colombier enum {
245e96a66cSDavid du Colombier 	NilBlock	= (~0UL),
255e96a66cSDavid du Colombier 	MaxBlock	= (1UL<<31),
265e96a66cSDavid du Colombier };
275e96a66cSDavid du Colombier 
285e96a66cSDavid du Colombier enum {
295e96a66cSDavid du Colombier 	HeaderMagic = 0x3776ae89,
305e96a66cSDavid du Colombier 	HeaderVersion = 1,
315e96a66cSDavid du Colombier 	HeaderOffset = 128*1024,
325e96a66cSDavid du Colombier 	HeaderSize = 512,
335e96a66cSDavid du Colombier 	SuperMagic = 0x2340a3b1,
345e96a66cSDavid du Colombier 	SuperSize = 512,
355e96a66cSDavid du Colombier 	SuperVersion = 1,
365e96a66cSDavid du Colombier 	LabelSize = 14,
375e96a66cSDavid du Colombier };
385e96a66cSDavid du Colombier 
395e96a66cSDavid du Colombier /* well known tags */
405e96a66cSDavid du Colombier enum {
415e96a66cSDavid du Colombier 	BadTag = 0,		/* this tag should not be used */
425e96a66cSDavid du Colombier 	RootTag = 1,		/* root of fs */
435e96a66cSDavid du Colombier 	EnumTag,		/* root of a dir listing */
445e96a66cSDavid du Colombier 	UserTag = 32,		/* all other tags should be >= UserTag */
455e96a66cSDavid du Colombier };
465e96a66cSDavid du Colombier 
475e96a66cSDavid du Colombier struct Super {
485e96a66cSDavid du Colombier 	u16int version;
495e96a66cSDavid du Colombier 	u32int epochLow;
505e96a66cSDavid du Colombier 	u32int epochHigh;
515e96a66cSDavid du Colombier 	u64int qid;			/* next qid */
525e96a66cSDavid du Colombier 	u32int active;			/* root of active file system */
535e96a66cSDavid du Colombier 	u32int next;			/* root of next snapshot to archive */
545e96a66cSDavid du Colombier 	u32int current;			/* root of snapshot currently archiving */
555e96a66cSDavid du Colombier 	uchar last[VtScoreSize];	/* last snapshot successfully archived */
565e96a66cSDavid du Colombier 	char name[128];			/* label */
575e96a66cSDavid du Colombier };
585e96a66cSDavid du Colombier 
595e96a66cSDavid du Colombier 
605e96a66cSDavid du Colombier struct Fs {
615e96a66cSDavid du Colombier 	Arch *arch;		/* immutable */
625e96a66cSDavid du Colombier 	Cache *cache;		/* immutable */
635e96a66cSDavid du Colombier 	int mode;		/* immutable */
645e96a66cSDavid du Colombier 	int blockSize;		/* immutable */
655e96a66cSDavid du Colombier 	VtSession *z;		/* immutable */
665e96a66cSDavid du Colombier 	Snap *snap;	/* immutable */
675e96a66cSDavid du Colombier 
685e96a66cSDavid du Colombier 	Periodic *metaFlush;	/* periodically flushes meta data cached in files */
695e96a66cSDavid du Colombier 
705e96a66cSDavid du Colombier 	/*
715e96a66cSDavid du Colombier 	 * epoch lock.
725e96a66cSDavid du Colombier 	 * Most operations on the fs require a read lock of elk, ensuring that
735e96a66cSDavid du Colombier 	 * the current high and low epochs do not change under foot.
745e96a66cSDavid du Colombier 	 * This lock is mostly acquired via a call to fileLock or fileRlock.
755e96a66cSDavid du Colombier 	 * Deletion and creation of snapshots occurs under a write lock of elk,
765e96a66cSDavid du Colombier 	 * ensuring no file operations are occurring concurrently.
775e96a66cSDavid du Colombier 	 */
785e96a66cSDavid du Colombier 	VtLock *elk;		/* epoch lock */
795e96a66cSDavid du Colombier 	u32int ehi;		/* epoch high */
805e96a66cSDavid du Colombier 	u32int elo;		/* epoch low */
815e96a66cSDavid du Colombier 
82*81cf8742SDavid du Colombier 	int halted;		/* epoch lock is held to halt (console initiated) */
83*81cf8742SDavid du Colombier 
845e96a66cSDavid du Colombier 	Source *source;		/* immutable: root of sources */
855e96a66cSDavid du Colombier 	File *file;		/* immutable: root of files */
865e96a66cSDavid du Colombier };
875e96a66cSDavid du Colombier 
885e96a66cSDavid du Colombier /*
895e96a66cSDavid du Colombier  * variant on VtEntry
905e96a66cSDavid du Colombier  * there are extra fields when stored locally
915e96a66cSDavid du Colombier  */
925e96a66cSDavid du Colombier struct Entry {
935e96a66cSDavid du Colombier 	u32int gen;			/* generation number */
945e96a66cSDavid du Colombier 	ushort psize;			/* pointer block size */
955e96a66cSDavid du Colombier 	ushort dsize;			/* data block size */
965e96a66cSDavid du Colombier 	uchar depth;			/* unpacked from flags */
975e96a66cSDavid du Colombier 	uchar flags;
985e96a66cSDavid du Colombier 	uvlong size;
995e96a66cSDavid du Colombier 	uchar score[VtScoreSize];
1005e96a66cSDavid du Colombier 	u32int tag;			/* tag for local blocks: zero if stored on Venti */
1015e96a66cSDavid du Colombier 	u32int snap;			/* non zero -> entering snapshot of given epoch */
1025e96a66cSDavid du Colombier 	uchar archive;			/* archive this snapshot: only valid for snap != 0 */
1035e96a66cSDavid du Colombier };
1045e96a66cSDavid du Colombier 
1055e96a66cSDavid du Colombier struct Source {
1065e96a66cSDavid du Colombier 	Fs *fs;		/* immutable */
1075e96a66cSDavid du Colombier 	int mode;	/* immutable */
1085e96a66cSDavid du Colombier 	u32int gen;	/* immutable */
1095e96a66cSDavid du Colombier 	int dsize;	/* immutable */
1105e96a66cSDavid du Colombier 	int dir;	/* immutable */
1115e96a66cSDavid du Colombier 
1125e96a66cSDavid du Colombier 	Source *parent;	/* immutable */
1135e96a66cSDavid du Colombier 
1145e96a66cSDavid du Colombier 	VtLock *lk;
1155e96a66cSDavid du Colombier 	int ref;
1165e96a66cSDavid du Colombier 	/*
1175e96a66cSDavid du Colombier 	 * epoch for the source
1185e96a66cSDavid du Colombier 	 * for ReadWrite sources, epoch is used to lazily notice
1195e96a66cSDavid du Colombier 	 * sources that must be split from the snapshots.
1205e96a66cSDavid du Colombier 	 * for ReadOnly sources, the epoch represents the minimum epoch
1215e96a66cSDavid du Colombier 	 * along the chain from the root, and is used to lazily notice
1225e96a66cSDavid du Colombier 	 * sources that have become invalid because they belong to an old
1235e96a66cSDavid du Colombier 	 * snapshot.
1245e96a66cSDavid du Colombier 	 */
1255e96a66cSDavid du Colombier 	u32int epoch;
1265e96a66cSDavid du Colombier 	Block *b;			/* block containing this source */
1275e96a66cSDavid du Colombier 	uchar score[VtScoreSize];	/* score of block containing this source */
1285e96a66cSDavid du Colombier 	u32int scoreEpoch;	/* epoch of block containing this source */
1295e96a66cSDavid du Colombier 	int epb;			/* immutable: entries per block in parent */
1305e96a66cSDavid du Colombier 	u32int tag;			/* immutable: tag of parent */
1315e96a66cSDavid du Colombier 	u32int offset; 			/* immutable: entry offset in parent */
1325e96a66cSDavid du Colombier };
1335e96a66cSDavid du Colombier 
1345e96a66cSDavid du Colombier 
1355e96a66cSDavid du Colombier struct Header {
1365e96a66cSDavid du Colombier 	ushort version;
1375e96a66cSDavid du Colombier 	ushort blockSize;
1385e96a66cSDavid du Colombier 	ulong super;	/* super blocks */
1395e96a66cSDavid du Colombier 	ulong label;	/* start of labels */
1405e96a66cSDavid du Colombier 	ulong data;	/* end of labels - start of data blocks */
1415e96a66cSDavid du Colombier 	ulong end;	/* end of data blocks */
1425e96a66cSDavid du Colombier };
1435e96a66cSDavid du Colombier 
1445e96a66cSDavid du Colombier /*
1455e96a66cSDavid du Colombier  * contains a one block buffer
1465e96a66cSDavid du Colombier  * to avoid problems of the block changing underfoot
1475e96a66cSDavid du Colombier  * and to enable an interface that supports unget.
1485e96a66cSDavid du Colombier  */
1495e96a66cSDavid du Colombier struct DirEntryEnum {
1505e96a66cSDavid du Colombier 	File *file;
1515e96a66cSDavid du Colombier 
1525e96a66cSDavid du Colombier 	u32int boff; 	/* block offset */
1535e96a66cSDavid du Colombier 
1545e96a66cSDavid du Colombier 	int i, n;
1555e96a66cSDavid du Colombier 	DirEntry *buf;
1565e96a66cSDavid du Colombier };
1575e96a66cSDavid du Colombier 
1585e96a66cSDavid du Colombier /* Block states; two orthogonal fields, Bv* and Ba* */
1595e96a66cSDavid du Colombier enum {
1605e96a66cSDavid du Colombier 	BsFree = 0,		/* available for allocation */
1615e96a66cSDavid du Colombier 	BsBad = 0xFF,		/* something is wrong with this block */
1625e96a66cSDavid du Colombier 
1635e96a66cSDavid du Colombier 	/* bit fields */
1645e96a66cSDavid du Colombier 	BsAlloc = 1<<0,	/* block is in use */
1655e96a66cSDavid du Colombier 	BsCopied = 1<<1,	/* block has been copied */
1665e96a66cSDavid du Colombier 	BsVenti = 1<<2,	/* block has been stored on Venti */
1675e96a66cSDavid du Colombier 	BsClosed = 1<<3,	/* block has been unlinked from active file system */
1685e96a66cSDavid du Colombier 	BsMask = BsAlloc|BsCopied|BsVenti|BsClosed,
1695e96a66cSDavid du Colombier };
1705e96a66cSDavid du Colombier 
1715e96a66cSDavid du Colombier /*
1725e96a66cSDavid du Colombier  * Each block has a state and generation
1735e96a66cSDavid du Colombier  * The following invariants are maintained
1745e96a66cSDavid du Colombier  * 	Each block has no more than than one parent per generation
1755e96a66cSDavid du Colombier  * 	For Active*, no child has a parent of a greater generation
1765e96a66cSDavid du Colombier  *	For Snap*, there is a snap parent of given generation and there are
1775e96a66cSDavid du Colombier  *		no parents of greater gen - implies no children snaps
1785e96a66cSDavid du Colombier  *		of a lesser gen
1795e96a66cSDavid du Colombier  *	For *RO, the block is fixed - no change can be made - all pointers
1805e96a66cSDavid du Colombier  *		are valid venti addresses
1815e96a66cSDavid du Colombier  *	For *A, the block is on the venti server
1825e96a66cSDavid du Colombier  *	There are no pointers to Zombie blocks
1835e96a66cSDavid du Colombier  *
1845e96a66cSDavid du Colombier  * Transitions
1855e96a66cSDavid du Colombier  *	Archiver at generation g
1865e96a66cSDavid du Colombier  *	Mutator at generation h
1875e96a66cSDavid du Colombier  *
1885e96a66cSDavid du Colombier  *	Want to modify a block
1895e96a66cSDavid du Colombier  *		Venti: create new Active(h)
1905e96a66cSDavid du Colombier  *		Active(x): x == h: do nothing
1915e96a66cSDavid du Colombier  *		Active(x): x < h: change to Snap(h-1) + add Active(h)
1925e96a66cSDavid du Colombier  *		ActiveRO(x): change to SnapRO(h-1) + add Active(h)
1935e96a66cSDavid du Colombier  *		ActiveA(x): add Active(h)
1945e96a66cSDavid du Colombier  *		Snap*(x): should not occur
1955e96a66cSDavid du Colombier  *		Zombie(x): should not occur
1965e96a66cSDavid du Colombier  *	Want to archive
1975e96a66cSDavid du Colombier  *		Active(x): x != g: should never happen
1985e96a66cSDavid du Colombier  *		Active(x): x == g fix children and free them: move to ActiveRO(g);
1995e96a66cSDavid du Colombier  *		ActiveRO(x): x != g: should never happen
2005e96a66cSDavid du Colombier  *		ActiveRO(x): x == g: wait until it hits ActiveA or SnapA
2015e96a66cSDavid du Colombier  *		ActiveA(x): done
2025e96a66cSDavid du Colombier  *		Snap(x): x < g: should never happen
2035e96a66cSDavid du Colombier  *		Snap(x): x >= g: fix children, freeing all SnapA(y) x == y;
2045e96a66cSDavid du Colombier  *		SnapRO(x): wait until it hits SnapA
2055e96a66cSDavid du Colombier  *
2065e96a66cSDavid du Colombier  */
2075e96a66cSDavid du Colombier 
2085e96a66cSDavid du Colombier /*
2095e96a66cSDavid du Colombier  * block types
2105e96a66cSDavid du Colombier  * more regular than Venti block types
2115e96a66cSDavid du Colombier  * bit 3 -> block or data block
2125e96a66cSDavid du Colombier  * bits 2-0 -> level of block
2135e96a66cSDavid du Colombier  */
2145e96a66cSDavid du Colombier enum {
2155e96a66cSDavid du Colombier 	BtData,
2165e96a66cSDavid du Colombier 	BtDir = 1<<3,
2175e96a66cSDavid du Colombier 	BtLevelMask = 7,
2185e96a66cSDavid du Colombier 	BtMax = 1<<4,
2195e96a66cSDavid du Colombier };
2205e96a66cSDavid du Colombier 
2215e96a66cSDavid du Colombier /* io states */
2225e96a66cSDavid du Colombier enum {
2235e96a66cSDavid du Colombier 	BioEmpty,	/* label & data are not valid */
2245e96a66cSDavid du Colombier 	BioLabel,	/* label is good */
2255e96a66cSDavid du Colombier 	BioClean,	/* data is on the disk */
2265e96a66cSDavid du Colombier 	BioDirty,	/* data is not yet on the disk */
2275e96a66cSDavid du Colombier 	BioReading,	/* in process of reading data */
2285e96a66cSDavid du Colombier 	BioWriting,	/* in process of writing data */
2295e96a66cSDavid du Colombier 	BioReadError,	/* error reading: assume disk always handles write errors */
2305e96a66cSDavid du Colombier 	BioVentiError,	/* error reading from venti (probably disconnected) */
2315e96a66cSDavid du Colombier 	BioMax
2325e96a66cSDavid du Colombier };
2335e96a66cSDavid du Colombier 
2345e96a66cSDavid du Colombier struct Label {
2355e96a66cSDavid du Colombier 	uchar type;
2365e96a66cSDavid du Colombier 	uchar state;
2375e96a66cSDavid du Colombier 	u32int tag;
2385e96a66cSDavid du Colombier 	u32int epoch;
2395e96a66cSDavid du Colombier 	u32int epochClose;
2405e96a66cSDavid du Colombier };
2415e96a66cSDavid du Colombier 
2425e96a66cSDavid du Colombier struct Block {
2435e96a66cSDavid du Colombier 	Cache *c;
2445e96a66cSDavid du Colombier 	int ref;
2455e96a66cSDavid du Colombier 	int nlock;
2465e96a66cSDavid du Colombier 	ulong	pc;		/* pc that fetched this block from the cache */
2475e96a66cSDavid du Colombier 
2485e96a66cSDavid du Colombier 	VtLock *lk;
2495e96a66cSDavid du Colombier 
2505e96a66cSDavid du Colombier 	int 	part;
2515e96a66cSDavid du Colombier 	u32int	addr;
2525e96a66cSDavid du Colombier 	uchar	score[VtScoreSize];	/* score */
2535e96a66cSDavid du Colombier 	Label l;
2545e96a66cSDavid du Colombier 
25561201b97SDavid du Colombier 	uchar	*dmap;
25661201b97SDavid du Colombier 
2575e96a66cSDavid du Colombier 	uchar 	*data;
2585e96a66cSDavid du Colombier 
2595e96a66cSDavid du Colombier 	/* the following is private; used by cache */
2605e96a66cSDavid du Colombier 
2615e96a66cSDavid du Colombier 	Block	*next;			/* doubly linked hash chains */
2625e96a66cSDavid du Colombier 	Block	**prev;
2635e96a66cSDavid du Colombier 	u32int	heap;			/* index in heap table */
2645e96a66cSDavid du Colombier 	u32int	used;			/* last reference times */
2655e96a66cSDavid du Colombier 
2665e96a66cSDavid du Colombier 	u32int	vers;			/* version of dirty flag */
2675e96a66cSDavid du Colombier 
2685e96a66cSDavid du Colombier 	BList	*uhead;			/* blocks to unlink when this block is written */
2695e96a66cSDavid du Colombier 	BList	*utail;
2705e96a66cSDavid du Colombier 
2715e96a66cSDavid du Colombier 	/* block ordering for cache -> disk */
2725e96a66cSDavid du Colombier 	BList	*prior;			/* list of blocks before this one */
2735e96a66cSDavid du Colombier 
2745e96a66cSDavid du Colombier 	Block	*ionext;
2755e96a66cSDavid du Colombier 	int	iostate;
2765e96a66cSDavid du Colombier 	VtRendez *ioready;
2775e96a66cSDavid du Colombier };
2785e96a66cSDavid du Colombier 
2795e96a66cSDavid du Colombier /* tree walker, for gc and archiver */
2805e96a66cSDavid du Colombier struct WalkPtr
2815e96a66cSDavid du Colombier {
2825e96a66cSDavid du Colombier 	uchar *data;
2835e96a66cSDavid du Colombier 	int isEntry;
2845e96a66cSDavid du Colombier 	int n;
2855e96a66cSDavid du Colombier 	int m;
2865e96a66cSDavid du Colombier 	Entry e;
2875e96a66cSDavid du Colombier 	uchar type;
2885e96a66cSDavid du Colombier 	u32int tag;
2895e96a66cSDavid du Colombier };
2905e96a66cSDavid du Colombier 
2915e96a66cSDavid du Colombier /* disk partitions */
2925e96a66cSDavid du Colombier enum {
2935e96a66cSDavid du Colombier 	PartError,
2945e96a66cSDavid du Colombier 	PartSuper,
2955e96a66cSDavid du Colombier 	PartLabel,
2965e96a66cSDavid du Colombier 	PartData,
2975e96a66cSDavid du Colombier 	PartVenti,	/* fake partition */
2985e96a66cSDavid du Colombier };
2995e96a66cSDavid du Colombier 
3005e96a66cSDavid du Colombier extern vtType[BtMax];
301