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