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