code: mafs

ref: b5d191e8cfa4fac05a02ea309df2541a2652ff23
dir: /dat.h/

View raw version
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;

enum
{
	KiB	= 1024ULL,	/* Kibibytes */
	MiB	= KiB*KiB,	/* Mibibytes */
	GiB	= KiB*MiB,	/* Gibibytes */
	TiB	= KiB*GiB,	/* Tibibytes */

	Nusers	= 32,	/* max. number of users */
	None	= 0,	/* user ID for "none" */
	Noworld	= 9999,	/* conventional id for "noworld" group */
	Userlen = 32,
	Nsec	= 1000ULL*1000*1000,
	Usec	= 1000ULL*1000,
	Msec	= 1000ULL,
	MAXRPC	= 8192ULL,
	Nbkp	= 2,

	/* Qpnone is the Tag.path of free blocks/extents(Tfree),
		and zero'ed out dentry blocks */
	Qpnone = 0,
	Qpmagic	= 1,	/* magic block Tag.qpath */
	Qpconfig = 2,	/* /adm/config block Tag.qpath */
	Qpsuper	= 3,	/* /adm/super block Tag.qpath */

	Qpadm	= 5,	/* /adm */
	Qpusers	= 6,	/* /adm/users */
	Qpbkp	= 7,	/* /adm/bkp block Tag.qpath */
	Qpconfig0 = 8,	/* /adm/bkp/config.0 block Tag.qpath */
	Qpsuper0 = 9,	/* /adm/bkp/super.0 block Tag.qpath */
	Qproot0	= 10,	/* /adm/bkp/root.0 block Tag.qpath */
	Qpconfig1 = 11,	/* /adm/bkp/config.1 block Tag.qpath */
	Qpsuper1 = 12,	/* /adm/bkp/super.1 block Tag.qpath */
	Qproot1	= 13,	/* /adm/bkp/root.1 block Tag.qpath */
	Qpctl = 14,		/* /adm/ctl */
	Qpfrees = 15,	/* /adm/frees block Tag.qpath */
	Nqidgen	= 64,
	Qproot	= Nqidgen-1, /* /, so fscreate() can disallow any create's below */

	/* check qpath for overflows - TODO, should be 2^64 */
	Maxqpath = 72057594037927936ULL, /* 2^56 */
};

/*
 * 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.
 */
enum {
	Rawblocksize= 512ULL,	/* real block size */
	Ndblock	= 32,	/* number of direct blocks in a Dentry */
	Niblock	= 6,	/* maximum depth of indirect blocks */

	/* global block numbers. The bkp contents locations are calculated by ream() */
	Bmagicb	= 0,	/* block number of first block. Bmagic conflicts with bio.h */
	Bconfig	= 1,	/* block number of config contents */
	Bsuper	= 2,	/* block number of super contents */
	Broot	= 3,	/* block number of root directory */
	Badm	= 4,	/* block number of /adm directory */
	Bdconfig = 5,	/* block number of /adm/config dentry */
	Bdsuper	= 6,	/* block number of /adm/super dentry */
	Bdusers	= 7,	/* block number of /adm/users file */
	Busers	= 8,	/* block number of /adm/users file contents */
	Bbkp	= 9,	/* block number of /adm/bkp directory */
	Bdconfig0 = 10,	/* block number of /adm/bkp/config.0 dentry */
	Bdsuper0 = 11,	/* block number of /adm/bkp/super.0 dentry */
	Bdroot0	= 12,	/* block number of /adm/bkp/root.0 dentry */
	Bdconfig1 = 13,	/* block number of /adm/bkp/config.1 dentry */
	Bdsuper1 = 14,	/* block number of /adm/bkp/super.1 dentry */
	Bdroot1	= 15,	/* block number of /adm/bkp/root.1 dentry */
	Bdctl	= 16,	/* block number of /adm/ctl dentry, empty contents, virtual file */
	Bdfrees = 17,	/* block number of /adm/frees dentry, text file of free extents */
	Nbused, /* blocks used up by default */
	Nminblocks = Nbused+(Nbkp*3), /* number of blocks used by the above and the backup blocks */

	Nthdirty = 9,	/* dirty byte is the 9th byte in the Tag */
};

typedef	struct	Config	Config;
typedef	struct	Content	Content;
typedef	struct	Dentry1	Dentry1;
typedef	struct	Dentry	Dentry;
typedef	struct	Fblock	Fblock;
typedef struct	Qid9p1	Qid9p1;
typedef	union	Rabuf	Rabuf;
typedef	struct	Super1	Super1;
typedef	struct	Superb	Superb;
typedef	struct	Tag	Tag;
typedef	struct	User	User;
typedef struct	Aux Aux;
typedef struct	Log Log;

typedef	struct	P9call	P9call;
typedef	struct	Tlock	Tlock;
typedef	struct	Uid	Uid;

/*
 * DONT TOUCH -- data structures stored on disk
 */
#pragma pack on
/* DONT TOUCH, this is the disk structure */
struct Tag
{
	u8 type;	/* Tmagic, Tdentry, Tdata, Tindn */
	u64 path;	/* Qid.path, unique identifier */
};

/* DONT TOUCH, this is the disk structure */
struct Super1
{
	u64 start;	/* starting block */
	u64 tfree;	/* total number of free blocks - obsolete? */
	u64 qidgen;	/* generator for unique ids. starts from 1024. */

	u64 frees;	/* list of free extents was written here at halt */
			/* make fsok a time stamp with the highest bit being the fsok flag */
	u64 fsok;	/* fsck status, using 64 bits to keep it all aligned */
};

/* DONT TOUCH, this is the disk structure */
struct Qid9p1
{
	u32 version;
	u64 path;	/* unique identifier */
};

/* DONT TOUCH, this is the disk structure */
/*
 * 1 dentry per block
 * no access time
 */
struct Dentry1
{
	Qid9p1	qid;
	u64 size;		/* 0 for directories. For files, size in bytes of the content */
	u64 pdblkno; 	/* block number of the parent directory entry. Will be 0 for root. */
	u64 pqpath; 	/* parent qid.path */
	u64 mtime;		/* modified time in nano seconds from epoch */
	u32 mode;		/* same bits as defined in /sys/include/libc.h:/Dir\.mode/ */
	s16 uid;
	s16 gid;
	s16 muid;
	u64 dblocks[Ndblock];	/* direct blocks. */
						/* List of Tdata block numbers for files and
							Tdentry block numbers for directories */
						/* Tag.type = Tdentry for directories and Tdata for files */
	u64 iblocks[Niblock];	/* indirect blocks */
};

#pragma pack off

/*
 * derived constants
 * Ndentriesperblock number of Dentry's in a block
 * Nindperblock number of block pointers in a block
 */
enum {
	Blocksize	= Rawblocksize - sizeof(Tag),
	Namelen	= (Blocksize-sizeof(Dentry1)),	/* maximum size of the name of a file or directory */

	Iounit		= MAXRPC, /* in bytes */
	Ntogether	= (Iounit/Blocksize)+1,		/* max probable size for jumbo writes */

	Ndentryperblock	= 1, /* Blocksize/sizeof(Dentry), */
	Nindperblock	= Blocksize/sizeof(u64),/* number of pointers per block */
};

#pragma pack on
/* DONT TOUCH, this is the disk structure */
struct Dentry
{
	struct	Dentry1;
	char	name[Namelen];
};
struct Content	/* used to unmarshall the disk contents */
{
	union{
		u8 buf[Blocksize];
		u64 bufa[Nindperblock];
		Dentry d;
	};
	Tag;
};
#pragma pack off

#pragma pack on
/* DONT TOUCH, this is the disk structure */
struct Superb
{
	Super1;
};
#pragma pack off

/*
 * array of qids that are locked
 */
struct Tlock
{
	u64 time;
	u64 qpath;
	u64 dblkno;
	Tlock *prev, *next;
};

struct Aux
{
	u64 dblkno; /* dentry absolute block number */
	u16 uid;
	u8 tlocked;	/* for exclusive use files, flag to indicate lock */
	u64 dri;	/* directory index while reading a directory */
	/* u64 lastreadahead; TODO */
};

struct User
{
	s16 id;		/* user id */
	s16 lid;		/* id of the leader of group */
	s16 members[Nusers]; /* group table, member id's */
	int nmembers;		/* number of group entries */
	char name[Userlen];	/* user name */
	User *next;
};

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[Namelen];
};

enum
{
	Nworks = 1024,	/* make this a parameter? */
	Nprocs = 32,	/* make this a parameter? */
	Nlru  = 32,
};

/*
 * error codes generated from the file server
 */
enum
{
	Eaccess = 1,
	Ealloc,
	Eauth,
	Eauthmsg,
	Ebadname,
	Ebadspc,
	Ebadu,
	Ebroken,
	Echar,
	Econvert,
	Ecount,
	Edir1,
	Edir2,
	Edirty,
	Edot,
	Eempty,
	Eentry,
	Eexist,
	Efid,
	Efidinuse,
	Efull,
	Einval,
	Elocked,
	Emode,
	Ename,
	Enomem,
	Enotd,
	Enotdir,
	Enotg,
	Enotl,
	Enotm,
	Enotu,
	Enotw,
	Eoffset,
	Eopen,
	Eperm,
	Ephase,
	Eqid,
	Eqidmode,
	Eronly,
	Ersc,
	Eshutdown,
	Esystem,
	Etoolong,
	Etoou64,
	Ewalk,

	MAXERR
};

/*
 * tags on block
 */
/* DONT TOUCH, this is in disk structures */
/* also, the order from Tdata to Tmaxind is exploited in indirck() & isdirty() */
enum
{
	Tblank = 0,
	Tfree  = 0,	/* free block */
	Tnone  = 0,
	Tmagic,		/* the first (zero'th) block holds the magic */
	Tdentry,	/* directory entry */
				/* Tdata & indirect blocks are last, to allow for greater depth */
	Tdata,		/* actual file contents */
	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 Tind2 block numbers */
	Tind4,		/* contains a list of Tind3 block numbers */
	Tind5,		/* contains a list of Tind4 block numbers, maximum file size 26 TiB */
	Maxtind,	/* should be Tind0+Niblock */
				/* gap for more indirect block depth in future */
	MAXTAG,

	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[Namelen];
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;