Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

typedef struct Arch Arch;
typedef struct BList BList;
typedef struct Block Block;
typedef struct Cache Cache;
typedef struct Disk Disk;
typedef struct Entry Entry;
typedef struct Fsck Fsck;
typedef struct Header Header;
typedef struct Label Label;
typedef struct Periodic Periodic;
typedef struct Snap Snap;
typedef struct Source Source;
typedef struct Super Super;
typedef struct WalkPtr WalkPtr;

#pragma incomplete Arch
#pragma incomplete BList
#pragma incomplete Cache
#pragma incomplete Disk
#pragma incomplete Periodic
#pragma incomplete Snap

/* tunable parameters - probably should not be constants */
enum {
        /*
         * estimate of bytes per dir entries - determines number
         * of index entries in the block
         */
        BytesPerEntry = 100,
        /* don't allocate in block if more than this percentage full */
        FullPercentage = 80,
        FlushSize = 200,        /* number of blocks to flush */
        DirtyPercentage = 50,   /* maximum percentage of dirty blocks */
};

enum {
        Nowaitlock,
        Waitlock,

        NilBlock        = (~0UL),
        MaxBlock        = (1UL<<31),
};

enum {
        HeaderMagic = 0x3776ae89,
        HeaderVersion = 1,
        HeaderOffset = 128*1024,
        HeaderSize = 512,
        SuperMagic = 0x2340a3b1,
        SuperSize = 512,
        SuperVersion = 1,
        LabelSize = 14,
};

/* well known tags */
enum {
        BadTag = 0,             /* this tag should not be used */
        RootTag = 1,            /* root of fs */
        EnumTag,                /* root of a dir listing */
        UserTag = 32,           /* all other tags should be >= UserTag */
};

struct Super {
        u16int version;
        u32int epochLow;
        u32int epochHigh;
        u64int qid;                     /* next qid */
        u32int active;                  /* root of active file system */
        u32int next;                    /* root of next snapshot to archive */
        u32int current;                 /* root of snapshot currently archiving */
        uchar last[VtScoreSize];        /* last snapshot successfully archived */
        char name[128];                 /* label */
};


struct Fs {
        Arch    *arch;          /* immutable */
        Cache   *cache;         /* immutable */
        int     mode;           /* immutable */
        int     noatimeupd;     /* immutable */
        int     blockSize;      /* immutable */
        VtSession *z;           /* immutable */
        Snap    *snap;          /* immutable */
        /* immutable; copy here & Fsys to ease error reporting */
        char    *name;

        Periodic *metaFlush; /* periodically flushes metadata cached in files */

        /*
         * epoch lock.
         * Most operations on the fs require a read lock of elk, ensuring that
         * the current high and low epochs do not change under foot.
         * This lock is mostly acquired via a call to fileLock or fileRlock.
         * Deletion and creation of snapshots occurs under a write lock of elk,
         * ensuring no file operations are occurring concurrently.
         */
        VtLock  *elk;           /* epoch lock */
        u32int  ehi;            /* epoch high */
        u32int  elo;            /* epoch low */

        int     halted; /* epoch lock is held to halt (console initiated) */

        Source  *source;        /* immutable: root of sources */
        File    *file;          /* immutable: root of files */
};

/*
 * variant on VtEntry
 * there are extra fields when stored locally
 */
struct Entry {
        u32int  gen;                    /* generation number */
        ushort  psize;                  /* pointer block size */
        ushort  dsize;                  /* data block size */
        uchar   depth;                  /* unpacked from flags */
        uchar   flags;
        uvlong  size;
        uchar   score[VtScoreSize];
        u32int  tag;    /* tag for local blocks: zero if stored on Venti */
        u32int  snap;   /* non-zero -> entering snapshot of given epoch */
        uchar   archive; /* archive this snapshot: only valid for snap != 0 */
};

/*
 * This is called a `stream' in the fossil paper.  There used to be Sinks too.
 * We believe that Sources and Files are one-to-one.
 */
struct Source {
        Fs      *fs;            /* immutable */
        int     mode;           /* immutable */
        int     issnapshot;     /* immutable */
        u32int  gen;            /* immutable */
        int     dsize;          /* immutable */
        int     dir;            /* immutable */

        Source  *parent;        /* immutable */
        File    *file;          /* immutable; point back */

        VtLock  *lk;
        int     ref;
        /*
         * epoch for the source
         * for ReadWrite sources, epoch is used to lazily notice
         * sources that must be split from the snapshots.
         * for ReadOnly sources, the epoch represents the minimum epoch
         * along the chain from the root, and is used to lazily notice
         * sources that have become invalid because they belong to an old
         * snapshot.
         */
        u32int  epoch;
        Block   *b;             /* block containing this source */
        uchar   score[VtScoreSize]; /* score of block containing this source */
        u32int  scoreEpoch;     /* epoch of block containing this source */
        int     epb;            /* immutable: entries per block in parent */
        u32int  tag;            /* immutable: tag of parent */
        u32int  offset;         /* immutable: entry offset in parent */
};


struct Header {
        ushort version;
        ushort blockSize;
        ulong super;    /* super blocks */
        ulong label;    /* start of labels */
        ulong data;     /* end of labels - start of data blocks */
        ulong end;      /* end of data blocks */
};

/*
 * contains a one block buffer
 * to avoid problems of the block changing underfoot
 * and to enable an interface that supports unget.
 */
struct DirEntryEnum {
        File    *file;

        u32int  boff;           /* block offset */

        int     i, n;
        DirEntry *buf;
};

/* Block states */
enum {
        BsFree = 0,             /* available for allocation */
        BsBad = 0xFF,           /* something is wrong with this block */

        /* bit fields */
        BsAlloc = 1<<0, /* block is in use */
        BsCopied = 1<<1,/* block has been copied (usually in preparation for unlink) */
        BsVenti = 1<<2, /* block has been stored on Venti */
        BsClosed = 1<<3,/* block has been unlinked on disk from active file system */
        BsMask = BsAlloc|BsCopied|BsVenti|BsClosed,
};

/*
 * block types
 * more regular than Venti block types
 * bit 3 -> block or data block
 * bits 2-0 -> level of block
 */
enum {
        BtData,
        BtDir = 1<<3,
        BtLevelMask = 7,
        BtMax = 1<<4,
};

/* io states */
enum {
        BioEmpty,       /* label & data are not valid */
        BioLabel,       /* label is good */
        BioClean,       /* data is on the disk */
        BioDirty,       /* data is not yet on the disk */
        BioReading,     /* in process of reading data */
        BioWriting,     /* in process of writing data */
        BioReadError,   /* error reading: assume disk always handles write errors */
        BioVentiError,  /* error reading from venti (probably disconnected) */
        BioMax
};

struct Label {
        uchar type;
        uchar state;
        u32int tag;
        u32int epoch;
        u32int epochClose;
};

struct Block {
        Cache   *c;
        int     ref;
        int     nlock;
        uintptr pc;             /* pc that fetched this block from the cache */

        VtLock  *lk;

        int     part;
        u32int  addr;
        uchar   score[VtScoreSize];     /* score */
        Label   l;

        uchar   *dmap;

        uchar   *data;

        /* the following is private; used by cache */

        Block   *next;                  /* doubly linked hash chains */
        Block   **prev;
        u32int  heap;                   /* index in heap table */
        u32int  used;                   /* last reference times */

        u32int  vers;                   /* version of dirty flag */

        BList   *uhead; /* blocks to unlink when this block is written */
        BList   *utail;

        /* block ordering for cache -> disk */
        BList   *prior;                 /* list of blocks before this one */

        Block   *ionext;
        int     iostate;
        VtRendez *ioready;
};

/* tree walker, for gc and archiver */
struct WalkPtr
{
        uchar   *data;
        int     isEntry;
        int     n;
        int     m;
        Entry   e;
        uchar   type;
        u32int  tag;
};

enum
{
        DoClose = 1<<0,
        DoClre = 1<<1,
        DoClri = 1<<2,
        DoClrp = 1<<3,
};

struct Fsck
{
        /* filled in by caller */
        int     printblocks;
        int     useventi;
        int     flags;
        int     printdirs;
        int     printfiles;
        int     walksnapshots;
        int     walkfs;
        Fs      *fs;
        int     (*print)(char*, ...);
        void    (*clre)(Fsck*, Block*, int);
        void    (*clrp)(Fsck*, Block*, int);
        void    (*close)(Fsck*, Block*, u32int);
        void    (*clri)(Fsck*, char*, MetaBlock*, int, Block*);

        /* used internally */
        Cache   *cache;
        uchar   *amap;  /* all blocks seen so far */
        uchar   *emap;  /* all blocks seen in this epoch */
        uchar   *xmap;  /* all blocks in this epoch with parents in this epoch */
        uchar   *errmap;        /* blocks with errors */
        uchar   *smap;          /* walked sources */
        int     nblocks;
        int     bsize;
        int     walkdepth;
        u32int  hint;           /* where the next root probably is */
        int     nseen;
        int     quantum;
        int     nclre;
        int     nclrp;
        int     nclose;
        int     nclri;
};

/* disk partitions; keep in sync with partname[] in disk.c */
enum {
        PartError,
        PartSuper,
        PartLabel,
        PartData,
        PartVenti,      /* fake partition */
};

extern vtType[BtMax];