xref: /plan9/sys/src/cmd/fossil/dat.h (revision f6333ca08b7dd0a0e01363c54d7dbcb6546f3681)
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 
235e96a66cSDavid du Colombier /* tuneable parameters - probably should not be constants */
245e96a66cSDavid du Colombier enum {
255e96a66cSDavid du Colombier 	BytesPerEntry = 100,	/* estimate of bytes per dir entries - determines number of index entries in the block */
265e96a66cSDavid du Colombier 	FullPercentage = 80,	/* don't allocate in block if more than this percentage full */
275e96a66cSDavid du Colombier 	FlushSize = 200,	/* number of blocks to flush */
285e96a66cSDavid du Colombier 	DirtyPercentage = 50,	/* maximum percentage of dirty blocks */
295e96a66cSDavid du Colombier };
305e96a66cSDavid du Colombier 
315e96a66cSDavid du Colombier enum {
325e96a66cSDavid du Colombier 	NilBlock	= (~0UL),
335e96a66cSDavid du Colombier 	MaxBlock	= (1UL<<31),
345e96a66cSDavid du Colombier };
355e96a66cSDavid du Colombier 
365e96a66cSDavid du Colombier enum {
375e96a66cSDavid du Colombier 	HeaderMagic = 0x3776ae89,
385e96a66cSDavid du Colombier 	HeaderVersion = 1,
395e96a66cSDavid du Colombier 	HeaderOffset = 128*1024,
405e96a66cSDavid du Colombier 	HeaderSize = 512,
415e96a66cSDavid du Colombier 	SuperMagic = 0x2340a3b1,
425e96a66cSDavid du Colombier 	SuperSize = 512,
435e96a66cSDavid du Colombier 	SuperVersion = 1,
445e96a66cSDavid du Colombier 	LabelSize = 14,
455e96a66cSDavid du Colombier };
465e96a66cSDavid du Colombier 
475e96a66cSDavid du Colombier /* well known tags */
485e96a66cSDavid du Colombier enum {
495e96a66cSDavid du Colombier 	BadTag = 0,		/* this tag should not be used */
505e96a66cSDavid du Colombier 	RootTag = 1,		/* root of fs */
515e96a66cSDavid du Colombier 	EnumTag,		/* root of a dir listing */
525e96a66cSDavid du Colombier 	UserTag = 32,		/* all other tags should be >= UserTag */
535e96a66cSDavid du Colombier };
545e96a66cSDavid du Colombier 
555e96a66cSDavid du Colombier struct Super {
565e96a66cSDavid du Colombier 	u16int version;
575e96a66cSDavid du Colombier 	u32int epochLow;
585e96a66cSDavid du Colombier 	u32int epochHigh;
595e96a66cSDavid du Colombier 	u64int qid;			/* next qid */
605e96a66cSDavid du Colombier 	u32int active;			/* root of active file system */
615e96a66cSDavid du Colombier 	u32int next;			/* root of next snapshot to archive */
625e96a66cSDavid du Colombier 	u32int current;			/* root of snapshot currently archiving */
635e96a66cSDavid du Colombier 	uchar last[VtScoreSize];	/* last snapshot successfully archived */
645e96a66cSDavid du Colombier 	char name[128];			/* label */
655e96a66cSDavid du Colombier };
665e96a66cSDavid du Colombier 
675e96a66cSDavid du Colombier 
685e96a66cSDavid du Colombier struct Fs {
695e96a66cSDavid du Colombier 	Arch *arch;		/* immutable */
705e96a66cSDavid du Colombier 	Cache *cache;		/* immutable */
715e96a66cSDavid du Colombier 	int mode;		/* immutable */
725e96a66cSDavid du Colombier 	int blockSize;		/* immutable */
735e96a66cSDavid du Colombier 	VtSession *z;		/* immutable */
745e96a66cSDavid du Colombier 	Snap *snap;	/* immutable */
755e96a66cSDavid du Colombier 
765e96a66cSDavid du Colombier 	Periodic *metaFlush;	/* periodically flushes meta data cached in files */
775e96a66cSDavid du Colombier 
785e96a66cSDavid du Colombier 	/*
795e96a66cSDavid du Colombier 	 * epoch lock.
805e96a66cSDavid du Colombier 	 * Most operations on the fs require a read lock of elk, ensuring that
815e96a66cSDavid du Colombier 	 * the current high and low epochs do not change under foot.
825e96a66cSDavid du Colombier 	 * This lock is mostly acquired via a call to fileLock or fileRlock.
835e96a66cSDavid du Colombier 	 * Deletion and creation of snapshots occurs under a write lock of elk,
845e96a66cSDavid du Colombier 	 * ensuring no file operations are occurring concurrently.
855e96a66cSDavid du Colombier 	 */
865e96a66cSDavid du Colombier 	VtLock *elk;		/* epoch lock */
875e96a66cSDavid du Colombier 	u32int ehi;		/* epoch high */
885e96a66cSDavid du Colombier 	u32int elo;		/* epoch low */
895e96a66cSDavid du Colombier 
9081cf8742SDavid du Colombier 	int halted;		/* epoch lock is held to halt (console initiated) */
9181cf8742SDavid du Colombier 
925e96a66cSDavid du Colombier 	Source *source;		/* immutable: root of sources */
935e96a66cSDavid du Colombier 	File *file;		/* immutable: root of files */
945e96a66cSDavid du Colombier };
955e96a66cSDavid du Colombier 
965e96a66cSDavid du Colombier /*
975e96a66cSDavid du Colombier  * variant on VtEntry
985e96a66cSDavid du Colombier  * there are extra fields when stored locally
995e96a66cSDavid du Colombier  */
1005e96a66cSDavid du Colombier struct Entry {
1015e96a66cSDavid du Colombier 	u32int gen;			/* generation number */
1025e96a66cSDavid du Colombier 	ushort psize;			/* pointer block size */
1035e96a66cSDavid du Colombier 	ushort dsize;			/* data block size */
1045e96a66cSDavid du Colombier 	uchar depth;			/* unpacked from flags */
1055e96a66cSDavid du Colombier 	uchar flags;
1065e96a66cSDavid du Colombier 	uvlong size;
1075e96a66cSDavid du Colombier 	uchar score[VtScoreSize];
1085e96a66cSDavid du Colombier 	u32int tag;			/* tag for local blocks: zero if stored on Venti */
1095e96a66cSDavid du Colombier 	u32int snap;			/* non zero -> entering snapshot of given epoch */
1105e96a66cSDavid du Colombier 	uchar archive;			/* archive this snapshot: only valid for snap != 0 */
1115e96a66cSDavid du Colombier };
1125e96a66cSDavid du Colombier 
1135e96a66cSDavid du Colombier struct Source {
1145e96a66cSDavid du Colombier 	Fs *fs;		/* immutable */
1155e96a66cSDavid du Colombier 	int mode;	/* immutable */
1165e96a66cSDavid du Colombier 	u32int gen;	/* immutable */
1175e96a66cSDavid du Colombier 	int dsize;	/* immutable */
1185e96a66cSDavid du Colombier 	int dir;	/* immutable */
1195e96a66cSDavid du Colombier 
1205e96a66cSDavid du Colombier 	Source *parent;	/* immutable */
1215e96a66cSDavid du Colombier 
1225e96a66cSDavid du Colombier 	VtLock *lk;
1235e96a66cSDavid du Colombier 	int ref;
1245e96a66cSDavid du Colombier 	/*
1255e96a66cSDavid du Colombier 	 * epoch for the source
1265e96a66cSDavid du Colombier 	 * for ReadWrite sources, epoch is used to lazily notice
1275e96a66cSDavid du Colombier 	 * sources that must be split from the snapshots.
1285e96a66cSDavid du Colombier 	 * for ReadOnly sources, the epoch represents the minimum epoch
1295e96a66cSDavid du Colombier 	 * along the chain from the root, and is used to lazily notice
1305e96a66cSDavid du Colombier 	 * sources that have become invalid because they belong to an old
1315e96a66cSDavid du Colombier 	 * snapshot.
1325e96a66cSDavid du Colombier 	 */
1335e96a66cSDavid du Colombier 	u32int epoch;
1345e96a66cSDavid du Colombier 	Block *b;			/* block containing this source */
1355e96a66cSDavid du Colombier 	uchar score[VtScoreSize];	/* score of block containing this source */
1365e96a66cSDavid du Colombier 	u32int scoreEpoch;	/* epoch of block containing this source */
1375e96a66cSDavid du Colombier 	int epb;			/* immutable: entries per block in parent */
1385e96a66cSDavid du Colombier 	u32int tag;			/* immutable: tag of parent */
1395e96a66cSDavid du Colombier 	u32int offset; 			/* immutable: entry offset in parent */
1405e96a66cSDavid du Colombier };
1415e96a66cSDavid du Colombier 
1425e96a66cSDavid du Colombier 
1435e96a66cSDavid du Colombier struct Header {
1445e96a66cSDavid du Colombier 	ushort version;
1455e96a66cSDavid du Colombier 	ushort blockSize;
1465e96a66cSDavid du Colombier 	ulong super;	/* super blocks */
1475e96a66cSDavid du Colombier 	ulong label;	/* start of labels */
1485e96a66cSDavid du Colombier 	ulong data;	/* end of labels - start of data blocks */
1495e96a66cSDavid du Colombier 	ulong end;	/* end of data blocks */
1505e96a66cSDavid du Colombier };
1515e96a66cSDavid du Colombier 
1525e96a66cSDavid du Colombier /*
1535e96a66cSDavid du Colombier  * contains a one block buffer
1545e96a66cSDavid du Colombier  * to avoid problems of the block changing underfoot
1555e96a66cSDavid du Colombier  * and to enable an interface that supports unget.
1565e96a66cSDavid du Colombier  */
1575e96a66cSDavid du Colombier struct DirEntryEnum {
1585e96a66cSDavid du Colombier 	File *file;
1595e96a66cSDavid du Colombier 
1605e96a66cSDavid du Colombier 	u32int boff; 	/* block offset */
1615e96a66cSDavid du Colombier 
1625e96a66cSDavid du Colombier 	int i, n;
1635e96a66cSDavid du Colombier 	DirEntry *buf;
1645e96a66cSDavid du Colombier };
1655e96a66cSDavid du Colombier 
166e569ccb5SDavid du Colombier /* Block states */
1675e96a66cSDavid du Colombier enum {
1685e96a66cSDavid du Colombier 	BsFree = 0,		/* available for allocation */
1695e96a66cSDavid du Colombier 	BsBad = 0xFF,		/* something is wrong with this block */
1705e96a66cSDavid du Colombier 
1715e96a66cSDavid du Colombier 	/* bit fields */
1725e96a66cSDavid du Colombier 	BsAlloc = 1<<0,	/* block is in use */
173e569ccb5SDavid du Colombier 	BsCopied = 1<<1,	/* block has been copied (usually in preparation for unlink) */
1745e96a66cSDavid du Colombier 	BsVenti = 1<<2,	/* block has been stored on Venti */
175e569ccb5SDavid du Colombier 	BsClosed = 1<<3,	/* block has been unlinked on disk from active file system */
1765e96a66cSDavid du Colombier 	BsMask = BsAlloc|BsCopied|BsVenti|BsClosed,
1775e96a66cSDavid du Colombier };
1785e96a66cSDavid du Colombier 
1795e96a66cSDavid du Colombier /*
1805e96a66cSDavid du Colombier  * block types
1815e96a66cSDavid du Colombier  * more regular than Venti block types
1825e96a66cSDavid du Colombier  * bit 3 -> block or data block
1835e96a66cSDavid du Colombier  * bits 2-0 -> level of block
1845e96a66cSDavid du Colombier  */
1855e96a66cSDavid du Colombier enum {
1865e96a66cSDavid du Colombier 	BtData,
1875e96a66cSDavid du Colombier 	BtDir = 1<<3,
1885e96a66cSDavid du Colombier 	BtLevelMask = 7,
1895e96a66cSDavid du Colombier 	BtMax = 1<<4,
1905e96a66cSDavid du Colombier };
1915e96a66cSDavid du Colombier 
1925e96a66cSDavid du Colombier /* io states */
1935e96a66cSDavid du Colombier enum {
1945e96a66cSDavid du Colombier 	BioEmpty,	/* label & data are not valid */
1955e96a66cSDavid du Colombier 	BioLabel,	/* label is good */
1965e96a66cSDavid du Colombier 	BioClean,	/* data is on the disk */
1975e96a66cSDavid du Colombier 	BioDirty,	/* data is not yet on the disk */
1985e96a66cSDavid du Colombier 	BioReading,	/* in process of reading data */
1995e96a66cSDavid du Colombier 	BioWriting,	/* in process of writing data */
2005e96a66cSDavid du Colombier 	BioReadError,	/* error reading: assume disk always handles write errors */
2015e96a66cSDavid du Colombier 	BioVentiError,	/* error reading from venti (probably disconnected) */
2025e96a66cSDavid du Colombier 	BioMax
2035e96a66cSDavid du Colombier };
2045e96a66cSDavid du Colombier 
2055e96a66cSDavid du Colombier struct Label {
2065e96a66cSDavid du Colombier 	uchar type;
2075e96a66cSDavid du Colombier 	uchar state;
2085e96a66cSDavid du Colombier 	u32int tag;
2095e96a66cSDavid du Colombier 	u32int epoch;
2105e96a66cSDavid du Colombier 	u32int epochClose;
2115e96a66cSDavid du Colombier };
2125e96a66cSDavid du Colombier 
2135e96a66cSDavid du Colombier struct Block {
2145e96a66cSDavid du Colombier 	Cache *c;
2155e96a66cSDavid du Colombier 	int ref;
2165e96a66cSDavid du Colombier 	int nlock;
21774f16c81SDavid du Colombier 	uintptr	pc;		/* pc that fetched this block from the cache */
2185e96a66cSDavid du Colombier 
2195e96a66cSDavid du Colombier 	VtLock *lk;
2205e96a66cSDavid du Colombier 
2215e96a66cSDavid du Colombier 	int 	part;
2225e96a66cSDavid du Colombier 	u32int	addr;
2235e96a66cSDavid du Colombier 	uchar	score[VtScoreSize];	/* score */
2245e96a66cSDavid du Colombier 	Label l;
2255e96a66cSDavid du Colombier 
22661201b97SDavid du Colombier 	uchar	*dmap;
22761201b97SDavid du Colombier 
2285e96a66cSDavid du Colombier 	uchar 	*data;
2295e96a66cSDavid du Colombier 
2305e96a66cSDavid du Colombier 	/* the following is private; used by cache */
2315e96a66cSDavid du Colombier 
2325e96a66cSDavid du Colombier 	Block	*next;			/* doubly linked hash chains */
2335e96a66cSDavid du Colombier 	Block	**prev;
2345e96a66cSDavid du Colombier 	u32int	heap;			/* index in heap table */
2355e96a66cSDavid du Colombier 	u32int	used;			/* last reference times */
2365e96a66cSDavid du Colombier 
2375e96a66cSDavid du Colombier 	u32int	vers;			/* version of dirty flag */
2385e96a66cSDavid du Colombier 
2395e96a66cSDavid du Colombier 	BList	*uhead;			/* blocks to unlink when this block is written */
2405e96a66cSDavid du Colombier 	BList	*utail;
2415e96a66cSDavid du Colombier 
2425e96a66cSDavid du Colombier 	/* block ordering for cache -> disk */
2435e96a66cSDavid du Colombier 	BList	*prior;			/* list of blocks before this one */
2445e96a66cSDavid du Colombier 
2455e96a66cSDavid du Colombier 	Block	*ionext;
2465e96a66cSDavid du Colombier 	int	iostate;
2475e96a66cSDavid du Colombier 	VtRendez *ioready;
2485e96a66cSDavid du Colombier };
2495e96a66cSDavid du Colombier 
2505e96a66cSDavid du Colombier /* tree walker, for gc and archiver */
2515e96a66cSDavid du Colombier struct WalkPtr
2525e96a66cSDavid du Colombier {
2535e96a66cSDavid du Colombier 	uchar *data;
2545e96a66cSDavid du Colombier 	int isEntry;
2555e96a66cSDavid du Colombier 	int n;
2565e96a66cSDavid du Colombier 	int m;
2575e96a66cSDavid du Colombier 	Entry e;
2585e96a66cSDavid du Colombier 	uchar type;
2595e96a66cSDavid du Colombier 	u32int tag;
2605e96a66cSDavid du Colombier };
2615e96a66cSDavid du Colombier 
262e569ccb5SDavid du Colombier enum
263e569ccb5SDavid du Colombier {
264e569ccb5SDavid du Colombier 	DoClose = 1<<0,
265e569ccb5SDavid du Colombier 	DoClre = 1<<1,
266e569ccb5SDavid du Colombier 	DoClri = 1<<2,
267e569ccb5SDavid du Colombier 	DoClrp = 1<<3,
268e569ccb5SDavid du Colombier };
269e569ccb5SDavid du Colombier 
270e569ccb5SDavid du Colombier struct Fsck
271e569ccb5SDavid du Colombier {
272e569ccb5SDavid du Colombier /* filled in by caller */
273e569ccb5SDavid du Colombier 	int printblocks;
274e569ccb5SDavid du Colombier 	int useventi;
275e569ccb5SDavid du Colombier 	int flags;
276e569ccb5SDavid du Colombier 	int printdirs;
277e569ccb5SDavid du Colombier 	int printfiles;
278e569ccb5SDavid du Colombier 	int walksnapshots;
279e569ccb5SDavid du Colombier 	int walkfs;
280e569ccb5SDavid du Colombier 	Fs *fs;
281e569ccb5SDavid du Colombier 	int (*print)(char*, ...);
282e569ccb5SDavid du Colombier 	void (*clre)(Fsck*, Block*, int);
283e569ccb5SDavid du Colombier 	void (*clrp)(Fsck*, Block*, int);
284e569ccb5SDavid du Colombier 	void (*close)(Fsck*, Block*, u32int);
285e569ccb5SDavid du Colombier 	void (*clri)(Fsck*, char*, MetaBlock*, int, Block*);
286e569ccb5SDavid du Colombier 
287e569ccb5SDavid du Colombier /* used internally */
288e569ccb5SDavid du Colombier 	Cache *cache;
289e569ccb5SDavid du Colombier 	uchar *amap;	/* all blocks seen so far */
290e569ccb5SDavid du Colombier 	uchar *emap;	/* all blocks seen in this epoch */
291e569ccb5SDavid du Colombier 	uchar *xmap;	/* all blocks in this epoch with parents in this epoch */
292e569ccb5SDavid du Colombier 	uchar *errmap;	/* blocks with errors */
293e569ccb5SDavid du Colombier 	uchar *smap;	/* walked sources */
294e569ccb5SDavid du Colombier 	int nblocks;
295e569ccb5SDavid du Colombier 	int bsize;
296e569ccb5SDavid du Colombier 	int walkdepth;
297e569ccb5SDavid du Colombier 	u32int hint;	/* where the next root probably is */
298e569ccb5SDavid du Colombier 	int nseen;
299e569ccb5SDavid du Colombier 	int quantum;
300e569ccb5SDavid du Colombier 	int nclre;
301e569ccb5SDavid du Colombier 	int nclrp;
302e569ccb5SDavid du Colombier 	int nclose;
303e569ccb5SDavid du Colombier 	int nclri;
304e569ccb5SDavid du Colombier };
305e569ccb5SDavid du Colombier 
306*f6333ca0SDavid du Colombier /* disk partitions; keep in sync with partname[] in disk.c */
3075e96a66cSDavid du Colombier enum {
3085e96a66cSDavid du Colombier 	PartError,
3095e96a66cSDavid du Colombier 	PartSuper,
3105e96a66cSDavid du Colombier 	PartLabel,
3115e96a66cSDavid du Colombier 	PartData,
3125e96a66cSDavid du Colombier 	PartVenti,	/* fake partition */
3135e96a66cSDavid du Colombier };
3145e96a66cSDavid du Colombier 
3155e96a66cSDavid du Colombier extern vtType[BtMax];
316