/*
* fundamental constants and types of the implementation
* changing any of these changes the layout on disk
*/
enum {
SUPER_ADDR = 2, /* block address of superblock */
ROOT_ADDR = 3, /* block address of root directory */
};
/* more fundamental types */
typedef vlong Wideoff; /* type to widen Off to for printing; ≥ as wide as Off */
typedef short Userid; /* signed internal representation of user-id */
typedef long Timet; /* in seconds since epoch */
typedef vlong Devsize; /* in bytes */
/* macros */
#define NEXT(x, l) (((x)+1) % (l))
#define PREV(x, l) ((x) == 0? (l)-1: (x)-1)
#define HOWMANY(x, y) (((x)+((y)-1)) / (y))
#define ROUNDUP(x, y) (HOWMANY((x), (y)) * (y))
#define TK2MS(t) (((ulong)(t)*1000)/HZ) /* ticks to ms - beware rounding */
#define MS2TK(t) (((ulong)(t)*HZ)/1000) /* ms to ticks - beware rounding */
#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
/* constants that don't affect disk layout */
enum {
MAXDAT = 8192, /* max allowable data message */
MAXMSG = 128, /* max protocol message sans data */
MB = 1024*1024,
HZ = 1, /* clock frequency */
};
/*
* tunable parameters
*/
enum {
Maxword = 256, /* max bytes per command-line word */
NTLOCK = 200, /* number of active file Tlocks */
};
typedef struct Auth Auth;
typedef struct Bp Bp;
typedef struct Bucket Bucket;
typedef struct Cache Cache;
typedef struct Centry Centry;
typedef struct Chan Chan;
typedef struct Command Command;
typedef struct Conf Conf;
typedef struct Cons Cons;
typedef struct Dentry Dentry;
typedef struct Device Device;
typedef struct Fbuf Fbuf;
typedef struct File File;
typedef struct Filsys Filsys;
typedef struct Filter Filter;
typedef struct Flag Flag;
typedef struct Hiob Hiob;
typedef struct Iobuf Iobuf;
typedef struct Lock Lock;
typedef struct Msgbuf Msgbuf;
typedef struct QLock QLock;
typedef struct Qid9p1 Qid9p1;
typedef struct Queue Queue;
typedef union Rabuf Rabuf;
typedef struct Rendez Rendez;
typedef struct Rtc Rtc;
typedef struct Startsb Startsb;
typedef struct Super1 Super1;
typedef struct Superb Superb;
typedef struct Tag Tag;
typedef struct Time Time;
typedef struct Tlock Tlock;
typedef struct Tm Tm;
typedef struct Uid Uid;
typedef struct Wpath Wpath;
#pragma incomplete Auth
struct Tag
{
short pad; /* make tag end at a long boundary */
short tag;
Off path;
};
/* DONT TOUCH, this is the disk structure */
struct Qid9p1
{
Off path; /* was long */
ulong version; /* should be Off */
};
/* DONT TOUCH, this is the disk structure */
struct Super1
{
Off fstart;
Off fsize;
Off tfree;
Off qidgen; /* generator for unique ids */
/*
* Stuff for WWC device
*/
Off cwraddr; /* cfs root addr */
Off roraddr; /* dump root addr */
Off last; /* last super block addr */
Off next; /* next super block addr */
};
/* DONT TOUCH, this is the disk structure */
struct Centry
{
ushort age;
short state;
Off waddr; /* worm addr */
};
/* DONT TOUCH, this is the disk structure */
struct Dentry
{
char name[NAMELEN];
Userid uid;
Userid gid;
ushort mode;
#define DALLOC 0x8000
#define DDIR 0x4000
#define DAPND 0x2000
#define DLOCK 0x1000
#define DREAD 0x4
#define DWRITE 0x2
#define DEXEC 0x1
Userid muid;
Qid9p1 qid;
Off size;
Off dblock[NDBLOCK];
Off iblocks[NIBLOCK];
long atime;
long mtime;
};
/*
* derived constants
*/
enum {
BUFSIZE = RBUFSIZE - sizeof(Tag),
DIRPERBUF = BUFSIZE / sizeof(Dentry),
INDPERBUF = BUFSIZE / sizeof(Off),
FEPERBUF = (BUFSIZE-sizeof(Super1)-sizeof(Off)) / sizeof(Off),
SMALLBUF = MAXMSG,
LARGEBUF = MAXMSG+MAXDAT+256,
RAGAP = (300*1024)/BUFSIZE, /* readahead parameter */
BKPERBLK = 10,
CEPERBK = (BUFSIZE - BKPERBLK*sizeof(Off)) /
(sizeof(Centry)*BKPERBLK),
};
/*
* send/recv queue structure
*/
struct Queue
{
QLock; /* to manipulate values */
Rendez empty;
Rendez full;
int waitedfor; /* flag */
char* name; /* for debugging */
int size; /* size of queue */
int loc; /* circular pointer */
int count; /* how many in queue */
void* args[1]; /* list of saved pointers, [->size] */
};
struct Device
{
uchar type;
uchar init;
Device* link; /* link for mcat/mlev/mirror */
Device* dlink; /* link all devices */
void* private;
Devsize size;
union {
struct { /* disk, (l)worm in j.j, sides */
int ctrl; /* disks only */
int targ;
int lun; /* not implemented in sd(3) */
int mapped;
char* file; /* ordinary file or dir instead */
int fd;
char* sddir; /* /dev/sdXX name, for juke drives */
char* sddata; /* /dev/sdXX/data or other file */
} wren;
struct { /* mcat mlev mirror */
Device* first;
Device* last;
int ndev;
} cat;
struct { /* cw */
Device* c; /* cache device */
Device* w; /* worm device */
Device* ro; /* dump - readonly */
} cw;
struct { /* juke */
Device* j; /* (robotics, worm drives) - wrens */
Device* m; /* (sides) - r or l devices */
} j;
struct { /* ro */
Device* parent;
} ro;
struct { /* fworm */
Device* fw;
} fw;
struct { /* part */
Device* d;
long base; /* percentages */
long size;
} part;
struct { /* byte-swapped */
Device* d;
} swab;
};
};
typedef struct Sidestarts {
Devsize sstart; /* blocks before start of side */
Devsize s1start; /* blocks before start of next side */
} Sidestarts;
union Rabuf {
struct {
Device* dev;
Off addr;
};
Rabuf* link;
};
struct Hiob
{
Iobuf* link;
Lock;
};
/* a 9P connection */
struct Chan
{
char type; /* major driver type i.e. Dev* */
int (*protocol)(Msgbuf*); /* version */
int msize; /* version */
char whochan[50];
char whoname[NAMELEN];
void (*whoprint)(Chan*);
ulong flags;
int chan; /* overall channel #, mostly for printing */
int nmsgs; /* outstanding messages, set under flock -- for flush */
Timet whotime;
int nfile; /* used by cmd_files */
RWLock reflock;
Chan* next; /* link list of chans */
Queue* send;
Queue* reply;
uchar authinfo[64];
void* pdata; /* sometimes is a Netconn* */
};
struct Filsys
{
char* name; /* name of filsys */
char* conf; /* symbolic configuration */
Device* dev; /* device that filsys is on */
int flags;
#define FREAM (1<<0) /* mkfs */
#define FRECOVER (1<<1) /* install last dump */
#define FEDIT (1<<2) /* modified */
};
struct Startsb
{
char* name;
Off startsb;
};
struct Time
{
Timet lasttoy;
Timet offset;
};
/*
* array of qids that are locked
*/
struct Tlock
{
Device* dev;
Timet time;
Off qpath;
File* file;
};
struct Cons
{
ulong flags; /* overall flags for all channels */
QLock; /* generic qlock for mutex */
int uid; /* botch -- used to get uid on cons_create */
int gid; /* botch -- used to get gid on cons_create */
int nuid; /* number of uids */
int ngid; /* number of gids */
Off offset; /* used to read files, c.f. fchar */
int chano; /* generator for channel numbers */
Chan* chan; /* console channel */
Filsys* curfs; /* current filesystem */
int profile; /* are we profiling? */
long* profbuf;
ulong minpc;
ulong maxpc;
ulong nprofbuf;
long nlarge; /* number of large message buffers */
long nsmall; /* ... small ... */
long nwormre; /* worm read errors */
long nwormwe; /* worm write errors */
long nwormhit; /* worm read cache hits */
long nwormmiss; /* worm read cache non-hits */
int noage; /* dont update cache age, dump and check */
long nwrenre; /* disk read errors */
long nwrenwe; /* disk write errors */
long nreseq; /* cache bucket resequence */
// Filter work[3]; /* thruput in messages */
// Filter rate[3]; /* thruput in bytes */
// Filter bhit[3]; /* getbufs that hit */
// Filter bread[3]; /* getbufs that miss and read */
// Filter brahead[3]; /* messages to readahead */
// Filter binit[3]; /* getbufs that miss and dont read */
};
struct File
{
QLock;
Qid qid;
Wpath* wpath;
Chan* cp; /* null means a free slot */
Tlock* tlock; /* if file is locked */
File* next; /* in cp->flist */
Filsys* fs;
Off addr;
long slot; /* ordinal # of Dentry with a directory block */
Off lastra; /* read ahead address */
ulong fid;
Userid uid;
Auth *auth;
char open;
#define FREAD 1
#define FWRITE 2
#define FREMOV 4
Off doffset; /* directory reading */
ulong dvers;
long dslot;
};
struct Wpath
{
Wpath* up; /* pointer upwards in path */
Off addr; /* directory entry addr */
long slot; /* directory entry slot */
short refs; /* number of files using this structure */
};
struct Iobuf
{
QLock;
Device* dev;
Iobuf* fore; /* for lru */
Iobuf* back; /* for lru */
char* iobuf; /* only active while locked */
char* xiobuf; /* "real" buffer pointer */
Off addr;
int flags;
};
struct Uid
{
Userid uid; /* user id */
Userid lead; /* leader of group */
Userid *gtab; /* group table */
int ngrp; /* number of group entries */
char name[NAMELEN]; /* user name */
};
/* DONT TOUCH, this is the disk structure */
struct Fbuf
{
Off nfree;
Off free[FEPERBUF];
};
/* DONT TOUCH, this is the disk structure */
struct Superb
{
Fbuf fbuf;
Super1;
};
struct Conf
{
ulong nmach; /* processors */
ulong mem; /* total physical bytes of memory */
ulong nuid; /* distinct uids */
ulong nserve; /* server processes */
ulong nfile; /* number of fid -- system wide */
ulong nwpath; /* number of active paths, derived from nfile */
ulong gidspace; /* space for gid names -- derived from nuid */
ulong nlgmsg; /* number of large message buffers */
ulong nsmmsg; /* number of small message buffers */
Off recovcw; /* recover addresses */
Off recovro;
Off firstsb;
Off recovsb;
ulong configfirst; /* configure before starting normal operation */
char *confdev;
char *devmap; /* name of config->file device mapping file */
ulong nauth; /* number of Auth structs */
uchar nodump; /* no periodic dumps */
uchar dumpreread; /* read and compare in dump copy */
};
enum {
Mbmagic = 0xb0ffe3,
};
/*
* message buffers
* 2 types, large and small
*/
struct Msgbuf
{
ulong magic;
short count;
short flags;
#define LARGE (1<<0)
#define FREE (1<<1)
#define BFREE (1<<2)
#define BTRACE (1<<7)
Chan* chan; /* file server conn within a net. conn */
Msgbuf* next;
uintptr param; /* misc. use; keep Conn* here */
int category;
uchar* data; /* rp or wp: current processing point */
uchar* xdata; /* base of allocation */
};
/*
* message buffer categories
*/
enum
{
Mxxx = 0,
Mbeth1,
Mbreply1,
Mbreply2,
Mbreply3,
Mbreply4,
MAXCAT,
};
enum { PRINTSIZE = 256 };
struct
{
Lock;
int machs;
int exiting;
} active;
struct Command
{
char* arg0;
char* help;
void (*func)(int, char*[]);
};
struct Flag
{
char* arg0;
char* help;
ulong flag;
};
struct Rtc
{
int sec;
int min;
int hour;
int mday;
int mon;
int year;
};
typedef struct
{
/* constants during a given truncation */
Dentry *d;
Iobuf *p; /* the block containing *d */
int uid;
Off newsize;
Off lastblk; /* last data block of file to keep */
/* variables */
Off relblk; /* # of current data blk within file */
int pastlast; /* have we walked past lastblk? */
int err;
} Truncstate;
/*
* cw device
*/
/* DONT TOUCH, this is the disk structure */
struct Cache
{
Off maddr; /* cache map addr */
Off msize; /* cache map size in buckets */
Off caddr; /* cache addr */
Off csize; /* cache size */
Off fsize; /* current size of worm */
Off wsize; /* max size of the worm */
Off wmax; /* highwater write */
Off sbaddr; /* super block addr */
Off cwraddr; /* cw root addr */
Off roraddr; /* dump root addr */
Timet toytime; /* somewhere convienent */
Timet time;
};
/* DONT TOUCH, this is the disk structure */
struct Bucket
{
long agegen; /* generator for ages in this bkt */
Centry entry[CEPERBK];
};
/* DONT TOUCH, this is in disk structures */
enum { Labmagic = 0xfeedfacedeadbeefULL, };
/* DONT TOUCH, this is the disk structure */
typedef struct Label Label;
struct Label /* label block on Devlworms, in last block */
{
uvlong magic;
ushort ord; /* side number within Juke */
char service[64]; /* documentation only */
};
typedef struct Map Map;
struct Map {
char *from;
Device *fdev;
char *to;
Device *tdev;
Map *next;
};
/*
* scsi i/o
*/
enum
{
SCSIread = 0,
SCSIwrite = 1,
};
/*
* Process states
*/
enum
{
Dead = 0,
Moribund,
Zombie,
Ready,
Scheding,
Running,
Queueing,
Sending,
Recving,
MMUing,
Exiting,
Inwait,
Wakeme,
Broken,
};
/*
* devnone block numbers
*/
enum
{
Cwio1 = 1,
Cwio2,
Cwxx1,
Cwxx2,
Cwxx3,
Cwxx4,
Cwdump1,
Cwdump2,
Cuidbuf,
Cckbuf,
};
/*
* error codes generated from the file server
*/
enum
{
Ebadspc = 1,
Efid,
Echar,
Eopen,
Ecount,
Ealloc,
Eqid,
Eaccess,
Eentry,
Emode,
Edir1,
Edir2,
Ephase,
Eexist,
Edot,
Eempty,
Ebadu,
Enoattach,
Ewstatb,
Ewstatd,
Ewstatg,
Ewstatl,
Ewstatm,
Ewstato,
Ewstatp,
Ewstatq,
Ewstatu,
Ewstatv,
Ename,
Ewalk,
Eronly,
Efull,
Eoffset,
Elocked,
Ebroken,
Eauth,
Eauth2,
Efidinuse,
Etoolong,
Econvert,
Eversion,
Eauthdisabled,
Eauthnone,
Eauthfile,
Eedge,
MAXERR
};
/*
* device types
*/
enum
{
Devnone = 0,
Devcon, /* console */
Devwren, /* disk drive */
Devworm, /* scsi optical drive */
Devlworm, /* scsi optical drive (labeled) */
Devfworm, /* fake read-only device */
Devjuke, /* scsi jukebox */
Devcw, /* cache with worm */
Devro, /* readonly worm */
Devmcat, /* multiple cat devices */
Devmlev, /* multiple interleave devices */
Devnet, /* network connection */
Devpart, /* partition */
Devfloppy, /* floppy drive */
Devswab, /* swab data between mem and device */
Devmirr, /* mirror devices */
MAXDEV
};
/*
* tags on block
*/
/* DONT TOUCH, this is in disk structures */
/* also, the order from Tdir to Tmaxind is exploited in indirck() & isdirty() */
enum
{
Tnone = 0,
Tsuper, /* the super block */
#ifdef COMPAT32
Tdir, /* directory contents */
Tind1, /* points to blocks */
Tind2, /* points to Tind1 */
#else
Tdirold,
Tind1old,
Tind2old,
#endif
Tfile, /* file contents; also defined in disk.h */
Tfree, /* in free list */
Tbuck, /* cache fs bucket */
Tvirgo, /* fake worm virgin bits */
Tcache, /* cw cache things */
Tconfig, /* configuration block */
#ifndef COMPAT32
/* Tdir & indirect blocks are last, to allow for greater depth */
Tdir, /* directory contents */
Tind1, /* points to blocks */
Tind2, /* points to Tind1 */
Tind3, /* points to Tind2 */
Tind4, /* points to Tind3 */
Maxtind,
#endif
/* gap for more indirect block depth in future */
Tlabel = 32, /* Devlworm label in last block */
MAXTAG,
#ifdef COMPAT32
Tmaxind = Tind2,
#else
Tmaxind = Maxtind - 1,
#endif
};
/*
* flags to getbuf
*/
enum
{
Brd = (1<<0), /* read the block if miss */
Bprobe = (1<<1), /* return null if miss */
Bmod = (1<<2), /* buffer is dirty, needs writing */
Bimm = (1<<3), /* write immediately on putbuf */
Bres = (1<<4), /* reserved, never renamed */
};
Conf conf;
Cons cons;
#pragma varargck type "Z" Device*
#pragma varargck type "T" Timet
#pragma varargck type "I" uchar*
#pragma varargck type "E" uchar*
#pragma varargck type "G" int
extern char *annstrs[];
extern Biobuf bin;
extern Map *devmap;
extern int (*fsprotocol[])(Msgbuf*);
|