1 typedef struct Arch Arch; 2 typedef struct BList BList; 3 typedef struct Block Block; 4 typedef struct Cache Cache; 5 typedef struct Disk Disk; 6 typedef struct Entry Entry; 7 typedef struct Fsck Fsck; 8 typedef struct Header Header; 9 typedef struct Label Label; 10 typedef struct Periodic Periodic; 11 typedef struct Snap Snap; 12 typedef struct Source Source; 13 typedef struct Super Super; 14 typedef struct WalkPtr WalkPtr; 15 16 #pragma incomplete Arch 17 #pragma incomplete BList 18 #pragma incomplete Cache 19 #pragma incomplete Disk 20 #pragma incomplete Periodic 21 #pragma incomplete Snap 22 23 /* tunable parameters - probably should not be constants */ 24 enum { 25 /* 26 * estimate of bytes per dir entries - determines number 27 * of index entries in the block 28 */ 29 BytesPerEntry = 100, 30 /* don't allocate in block if more than this percentage full */ 31 FullPercentage = 80, 32 FlushSize = 200, /* number of blocks to flush */ 33 DirtyPercentage = 50, /* maximum percentage of dirty blocks */ 34 }; 35 36 enum { 37 NilBlock = (~0UL), 38 MaxBlock = (1UL<<31), 39 }; 40 41 enum { 42 HeaderMagic = 0x3776ae89, 43 HeaderVersion = 1, 44 HeaderOffset = 128*1024, 45 HeaderSize = 512, 46 SuperMagic = 0x2340a3b1, 47 SuperSize = 512, 48 SuperVersion = 1, 49 LabelSize = 14, 50 }; 51 52 /* well known tags */ 53 enum { 54 BadTag = 0, /* this tag should not be used */ 55 RootTag = 1, /* root of fs */ 56 EnumTag, /* root of a dir listing */ 57 UserTag = 32, /* all other tags should be >= UserTag */ 58 }; 59 60 struct Super { 61 u16int version; 62 u32int epochLow; 63 u32int epochHigh; 64 u64int qid; /* next qid */ 65 u32int active; /* root of active file system */ 66 u32int next; /* root of next snapshot to archive */ 67 u32int current; /* root of snapshot currently archiving */ 68 uchar last[VtScoreSize]; /* last snapshot successfully archived */ 69 char name[128]; /* label */ 70 }; 71 72 73 struct Fs { 74 Arch *arch; /* immutable */ 75 Cache *cache; /* immutable */ 76 int mode; /* immutable */ 77 int blockSize; /* immutable */ 78 VtSession *z; /* immutable */ 79 Snap *snap; /* immutable */ 80 /* immutable; copy here & Fsys to ease error reporting */ 81 char *name; 82 83 Periodic *metaFlush; /* periodically flushes metadata cached in files */ 84 85 /* 86 * epoch lock. 87 * Most operations on the fs require a read lock of elk, ensuring that 88 * the current high and low epochs do not change under foot. 89 * This lock is mostly acquired via a call to fileLock or fileRlock. 90 * Deletion and creation of snapshots occurs under a write lock of elk, 91 * ensuring no file operations are occurring concurrently. 92 */ 93 VtLock *elk; /* epoch lock */ 94 u32int ehi; /* epoch high */ 95 u32int elo; /* epoch low */ 96 97 int halted; /* epoch lock is held to halt (console initiated) */ 98 99 Source *source; /* immutable: root of sources */ 100 File *file; /* immutable: root of files */ 101 }; 102 103 /* 104 * variant on VtEntry 105 * there are extra fields when stored locally 106 */ 107 struct Entry { 108 u32int gen; /* generation number */ 109 ushort psize; /* pointer block size */ 110 ushort dsize; /* data block size */ 111 uchar depth; /* unpacked from flags */ 112 uchar flags; 113 uvlong size; 114 uchar score[VtScoreSize]; 115 u32int tag; /* tag for local blocks: zero if stored on Venti */ 116 u32int snap; /* non-zero -> entering snapshot of given epoch */ 117 uchar archive; /* archive this snapshot: only valid for snap != 0 */ 118 }; 119 120 /* 121 * This is called a `stream' in the fossil paper. There used to be Sinks too. 122 * We believe that Sources and Files are one-to-one. 123 */ 124 struct Source { 125 Fs *fs; /* immutable */ 126 int mode; /* immutable */ 127 int issnapshot; /* immutable */ 128 u32int gen; /* immutable */ 129 int dsize; /* immutable */ 130 int dir; /* immutable */ 131 132 Source *parent; /* immutable */ 133 File *file; /* immutable; point back */ 134 135 VtLock *lk; 136 int ref; 137 /* 138 * epoch for the source 139 * for ReadWrite sources, epoch is used to lazily notice 140 * sources that must be split from the snapshots. 141 * for ReadOnly sources, the epoch represents the minimum epoch 142 * along the chain from the root, and is used to lazily notice 143 * sources that have become invalid because they belong to an old 144 * snapshot. 145 */ 146 u32int epoch; 147 Block *b; /* block containing this source */ 148 uchar score[VtScoreSize]; /* score of block containing this source */ 149 u32int scoreEpoch; /* epoch of block containing this source */ 150 int epb; /* immutable: entries per block in parent */ 151 u32int tag; /* immutable: tag of parent */ 152 u32int offset; /* immutable: entry offset in parent */ 153 }; 154 155 156 struct Header { 157 ushort version; 158 ushort blockSize; 159 ulong super; /* super blocks */ 160 ulong label; /* start of labels */ 161 ulong data; /* end of labels - start of data blocks */ 162 ulong end; /* end of data blocks */ 163 }; 164 165 /* 166 * contains a one block buffer 167 * to avoid problems of the block changing underfoot 168 * and to enable an interface that supports unget. 169 */ 170 struct DirEntryEnum { 171 File *file; 172 173 u32int boff; /* block offset */ 174 175 int i, n; 176 DirEntry *buf; 177 }; 178 179 /* Block states */ 180 enum { 181 BsFree = 0, /* available for allocation */ 182 BsBad = 0xFF, /* something is wrong with this block */ 183 184 /* bit fields */ 185 BsAlloc = 1<<0, /* block is in use */ 186 BsCopied = 1<<1,/* block has been copied (usually in preparation for unlink) */ 187 BsVenti = 1<<2, /* block has been stored on Venti */ 188 BsClosed = 1<<3,/* block has been unlinked on disk from active file system */ 189 BsMask = BsAlloc|BsCopied|BsVenti|BsClosed, 190 }; 191 192 /* 193 * block types 194 * more regular than Venti block types 195 * bit 3 -> block or data block 196 * bits 2-0 -> level of block 197 */ 198 enum { 199 BtData, 200 BtDir = 1<<3, 201 BtLevelMask = 7, 202 BtMax = 1<<4, 203 }; 204 205 /* io states */ 206 enum { 207 BioEmpty, /* label & data are not valid */ 208 BioLabel, /* label is good */ 209 BioClean, /* data is on the disk */ 210 BioDirty, /* data is not yet on the disk */ 211 BioReading, /* in process of reading data */ 212 BioWriting, /* in process of writing data */ 213 BioReadError, /* error reading: assume disk always handles write errors */ 214 BioVentiError, /* error reading from venti (probably disconnected) */ 215 BioMax 216 }; 217 218 struct Label { 219 uchar type; 220 uchar state; 221 u32int tag; 222 u32int epoch; 223 u32int epochClose; 224 }; 225 226 struct Block { 227 Cache *c; 228 int ref; 229 int nlock; 230 uintptr pc; /* pc that fetched this block from the cache */ 231 232 VtLock *lk; 233 234 int part; 235 u32int addr; 236 uchar score[VtScoreSize]; /* score */ 237 Label l; 238 239 uchar *dmap; 240 241 uchar *data; 242 243 /* the following is private; used by cache */ 244 245 Block *next; /* doubly linked hash chains */ 246 Block **prev; 247 u32int heap; /* index in heap table */ 248 u32int used; /* last reference times */ 249 250 u32int vers; /* version of dirty flag */ 251 252 BList *uhead; /* blocks to unlink when this block is written */ 253 BList *utail; 254 255 /* block ordering for cache -> disk */ 256 BList *prior; /* list of blocks before this one */ 257 258 Block *ionext; 259 int iostate; 260 VtRendez *ioready; 261 }; 262 263 /* tree walker, for gc and archiver */ 264 struct WalkPtr 265 { 266 uchar *data; 267 int isEntry; 268 int n; 269 int m; 270 Entry e; 271 uchar type; 272 u32int tag; 273 }; 274 275 enum 276 { 277 DoClose = 1<<0, 278 DoClre = 1<<1, 279 DoClri = 1<<2, 280 DoClrp = 1<<3, 281 }; 282 283 struct Fsck 284 { 285 /* filled in by caller */ 286 int printblocks; 287 int useventi; 288 int flags; 289 int printdirs; 290 int printfiles; 291 int walksnapshots; 292 int walkfs; 293 Fs *fs; 294 int (*print)(char*, ...); 295 void (*clre)(Fsck*, Block*, int); 296 void (*clrp)(Fsck*, Block*, int); 297 void (*close)(Fsck*, Block*, u32int); 298 void (*clri)(Fsck*, char*, MetaBlock*, int, Block*); 299 300 /* used internally */ 301 Cache *cache; 302 uchar *amap; /* all blocks seen so far */ 303 uchar *emap; /* all blocks seen in this epoch */ 304 uchar *xmap; /* all blocks in this epoch with parents in this epoch */ 305 uchar *errmap; /* blocks with errors */ 306 uchar *smap; /* walked sources */ 307 int nblocks; 308 int bsize; 309 int walkdepth; 310 u32int hint; /* where the next root probably is */ 311 int nseen; 312 int quantum; 313 int nclre; 314 int nclrp; 315 int nclose; 316 int nclri; 317 }; 318 319 /* disk partitions; keep in sync with partname[] in disk.c */ 320 enum { 321 PartError, 322 PartSuper, 323 PartLabel, 324 PartData, 325 PartVenti, /* fake partition */ 326 }; 327 328 extern vtType[BtMax]; 329