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