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