2 056fe1ba 2003-11-23 devnull * Memory-only VtBlock cache.
4 056fe1ba 2003-11-23 devnull * The cached Venti blocks are in the hash chains.
5 056fe1ba 2003-11-23 devnull * The cached local blocks are only in the blocks array.
6 056fe1ba 2003-11-23 devnull * The free blocks are in the heap, which is supposed to
7 056fe1ba 2003-11-23 devnull * be indexed by second-to-last use but actually
8 056fe1ba 2003-11-23 devnull * appears to be last use.
11 056fe1ba 2003-11-23 devnull #include <u.h>
12 056fe1ba 2003-11-23 devnull #include <libc.h>
13 056fe1ba 2003-11-23 devnull #include <venti.h>
15 056fe1ba 2003-11-23 devnull int nread, ncopy, nwrite;
18 056fe1ba 2003-11-23 devnull BioLocal = 1,
19 056fe1ba 2003-11-23 devnull BioVenti,
20 056fe1ba 2003-11-23 devnull BioReading,
21 056fe1ba 2003-11-23 devnull BioWriting,
22 056fe1ba 2003-11-23 devnull BioEmpty,
23 056fe1ba 2003-11-23 devnull BioVentiError,
26 056fe1ba 2003-11-23 devnull BadHeap = ~0,
28 056fe1ba 2003-11-23 devnull struct VtCache
30 056fe1ba 2003-11-23 devnull QLock lk;
31 056fe1ba 2003-11-23 devnull VtConn *z;
32 056fe1ba 2003-11-23 devnull u32int blocksize;
33 056fe1ba 2003-11-23 devnull u32int now; /* ticks for usage time stamps */
34 056fe1ba 2003-11-23 devnull VtBlock **hash; /* hash table for finding addresses */
35 056fe1ba 2003-11-23 devnull int nhash;
36 056fe1ba 2003-11-23 devnull VtBlock **heap; /* heap for finding victims */
37 056fe1ba 2003-11-23 devnull int nheap;
38 056fe1ba 2003-11-23 devnull VtBlock *block; /* all allocated blocks */
39 056fe1ba 2003-11-23 devnull int nblock;
40 056fe1ba 2003-11-23 devnull uchar *mem; /* memory for all blocks and data */
41 056fe1ba 2003-11-23 devnull int mode;
44 056fe1ba 2003-11-23 devnull static void cachecheck(VtCache*);
47 056fe1ba 2003-11-23 devnull vtcachealloc(VtConn *z, int blocksize, ulong nblock, int mode)
49 056fe1ba 2003-11-23 devnull uchar *p;
50 056fe1ba 2003-11-23 devnull VtCache *c;
52 056fe1ba 2003-11-23 devnull VtBlock *b;
54 056fe1ba 2003-11-23 devnull c = vtmallocz(sizeof(VtCache));
56 056fe1ba 2003-11-23 devnull c->z = z;
57 056fe1ba 2003-11-23 devnull c->blocksize = (blocksize + 127) & ~127;
58 056fe1ba 2003-11-23 devnull c->nblock = nblock;
60 056fe1ba 2003-11-23 devnull c->nhash = nblock;
61 056fe1ba 2003-11-23 devnull c->hash = vtmallocz(nblock*sizeof(VtBlock*));
62 056fe1ba 2003-11-23 devnull c->heap = vtmallocz(nblock*sizeof(VtBlock*));
63 056fe1ba 2003-11-23 devnull c->block = vtmallocz(nblock*sizeof(VtBlock));
64 056fe1ba 2003-11-23 devnull c->mem = vtmallocz(nblock*c->blocksize);
65 056fe1ba 2003-11-23 devnull c->mode = mode;
67 056fe1ba 2003-11-23 devnull p = c->mem;
68 056fe1ba 2003-11-23 devnull for(i=0; i<nblock; i++){
69 056fe1ba 2003-11-23 devnull b = &c->block[i];
70 056fe1ba 2003-11-23 devnull b->addr = NilBlock;
71 056fe1ba 2003-11-23 devnull b->c = c;
72 056fe1ba 2003-11-23 devnull b->data = p;
73 056fe1ba 2003-11-23 devnull b->heap = i;
74 056fe1ba 2003-11-23 devnull c->heap[i] = b;
75 056fe1ba 2003-11-23 devnull p += c->blocksize;
77 056fe1ba 2003-11-23 devnull c->nheap = nblock;
78 056fe1ba 2003-11-23 devnull cachecheck(c);
79 056fe1ba 2003-11-23 devnull return c;
83 056fe1ba 2003-11-23 devnull vtcachefree(VtCache *c)
87 056fe1ba 2003-11-23 devnull qlock(&c->lk);
89 056fe1ba 2003-11-23 devnull cachecheck(c);
90 056fe1ba 2003-11-23 devnull for(i=0; i<c->nblock; i++)
91 056fe1ba 2003-11-23 devnull assert(c->block[i].ref == 0);
93 056fe1ba 2003-11-23 devnull vtfree(c->hash);
94 056fe1ba 2003-11-23 devnull vtfree(c->heap);
95 056fe1ba 2003-11-23 devnull vtfree(c->block);
96 056fe1ba 2003-11-23 devnull vtfree(c->mem);
97 056fe1ba 2003-11-23 devnull vtfree(c);
100 056fe1ba 2003-11-23 devnull static void
101 056fe1ba 2003-11-23 devnull vtcachedump(VtCache *c)
104 056fe1ba 2003-11-23 devnull VtBlock *b;
106 056fe1ba 2003-11-23 devnull for(i=0; i<c->nblock; i++){
107 056fe1ba 2003-11-23 devnull b = &c->block[i];
108 056fe1ba 2003-11-23 devnull print("cache block %d: type %d score %V iostate %d addr %d ref %d nlock %d\n",
109 056fe1ba 2003-11-23 devnull i, b->type, b->score, b->iostate, b->addr, b->ref, b->nlock);
113 056fe1ba 2003-11-23 devnull static void
114 056fe1ba 2003-11-23 devnull cachecheck(VtCache *c)
116 056fe1ba 2003-11-23 devnull u32int size, now;
117 056fe1ba 2003-11-23 devnull int i, k, refed;
118 056fe1ba 2003-11-23 devnull VtBlock *b;
120 056fe1ba 2003-11-23 devnull size = c->blocksize;
121 056fe1ba 2003-11-23 devnull now = c->now;
123 056fe1ba 2003-11-23 devnull for(i = 0; i < c->nheap; i++){
124 056fe1ba 2003-11-23 devnull if(c->heap[i]->heap != i)
125 056fe1ba 2003-11-23 devnull sysfatal("mis-heaped at %d: %d", i, c->heap[i]->heap);
126 056fe1ba 2003-11-23 devnull if(i > 0 && c->heap[(i - 1) >> 1]->used - now > c->heap[i]->used - now)
127 056fe1ba 2003-11-23 devnull sysfatal("bad heap ordering");
128 056fe1ba 2003-11-23 devnull k = (i << 1) + 1;
129 056fe1ba 2003-11-23 devnull if(k < c->nheap && c->heap[i]->used - now > c->heap[k]->used - now)
130 056fe1ba 2003-11-23 devnull sysfatal("bad heap ordering");
132 056fe1ba 2003-11-23 devnull if(k < c->nheap && c->heap[i]->used - now > c->heap[k]->used - now)
133 056fe1ba 2003-11-23 devnull sysfatal("bad heap ordering");
136 056fe1ba 2003-11-23 devnull refed = 0;
137 056fe1ba 2003-11-23 devnull for(i = 0; i < c->nblock; i++){
138 056fe1ba 2003-11-23 devnull b = &c->block[i];
139 056fe1ba 2003-11-23 devnull if(b->data != &c->mem[i * size])
140 056fe1ba 2003-11-23 devnull sysfatal("mis-blocked at %d", i);
141 056fe1ba 2003-11-23 devnull if(b->ref && b->heap == BadHeap)
142 056fe1ba 2003-11-23 devnull refed++;
143 056fe1ba 2003-11-23 devnull else if(b->addr != NilBlock)
144 056fe1ba 2003-11-23 devnull refed++;
146 056fe1ba 2003-11-23 devnull if(c->nheap + refed != c->nblock){
147 056fe1ba 2003-11-23 devnull fprint(2, "cachecheck: nheap %d refed %d nblocks %d\n", c->nheap, refed, c->nblock);
148 056fe1ba 2003-11-23 devnull //vtcachedump(c);
150 056fe1ba 2003-11-23 devnull assert(c->nheap + refed == c->nblock);
151 056fe1ba 2003-11-23 devnull refed = 0;
152 056fe1ba 2003-11-23 devnull for(i = 0; i < c->nblock; i++){
153 056fe1ba 2003-11-23 devnull b = &c->block[i];
154 056fe1ba 2003-11-23 devnull if(b->ref){
155 056fe1ba 2003-11-23 devnull if(1)fprint(2, "a=%ud %V ref=%d\n", b->addr, b->score, b->ref);
156 056fe1ba 2003-11-23 devnull refed++;
159 056fe1ba 2003-11-23 devnull if(refed > 0)fprint(2, "cachecheck: in used %d\n", refed);
162 056fe1ba 2003-11-23 devnull static int
163 056fe1ba 2003-11-23 devnull upheap(int i, VtBlock *b)
165 056fe1ba 2003-11-23 devnull VtBlock *bb;
166 056fe1ba 2003-11-23 devnull u32int now;
168 056fe1ba 2003-11-23 devnull VtCache *c;
170 056fe1ba 2003-11-23 devnull c = b->c;
171 056fe1ba 2003-11-23 devnull now = c->now;
172 056fe1ba 2003-11-23 devnull for(; i != 0; i = p){
173 056fe1ba 2003-11-23 devnull p = (i - 1) >> 1;
174 056fe1ba 2003-11-23 devnull bb = c->heap[p];
175 056fe1ba 2003-11-23 devnull if(b->used - now >= bb->used - now)
177 056fe1ba 2003-11-23 devnull c->heap[i] = bb;
178 056fe1ba 2003-11-23 devnull bb->heap = i;
180 056fe1ba 2003-11-23 devnull c->heap[i] = b;
181 056fe1ba 2003-11-23 devnull b->heap = i;
183 056fe1ba 2003-11-23 devnull return i;
186 056fe1ba 2003-11-23 devnull static int
187 056fe1ba 2003-11-23 devnull downheap(int i, VtBlock *b)
189 056fe1ba 2003-11-23 devnull VtBlock *bb;
190 056fe1ba 2003-11-23 devnull u32int now;
192 056fe1ba 2003-11-23 devnull VtCache *c;
194 056fe1ba 2003-11-23 devnull c = b->c;
195 056fe1ba 2003-11-23 devnull now = c->now;
196 056fe1ba 2003-11-23 devnull for(; ; i = k){
197 056fe1ba 2003-11-23 devnull k = (i << 1) + 1;
198 056fe1ba 2003-11-23 devnull if(k >= c->nheap)
200 056fe1ba 2003-11-23 devnull if(k + 1 < c->nheap && c->heap[k]->used - now > c->heap[k + 1]->used - now)
202 056fe1ba 2003-11-23 devnull bb = c->heap[k];
203 056fe1ba 2003-11-23 devnull if(b->used - now <= bb->used - now)
205 056fe1ba 2003-11-23 devnull c->heap[i] = bb;
206 056fe1ba 2003-11-23 devnull bb->heap = i;
208 056fe1ba 2003-11-23 devnull c->heap[i] = b;
209 056fe1ba 2003-11-23 devnull b->heap = i;
210 056fe1ba 2003-11-23 devnull return i;
214 056fe1ba 2003-11-23 devnull * Delete a block from the heap.
215 056fe1ba 2003-11-23 devnull * Called with c->lk held.
217 056fe1ba 2003-11-23 devnull static void
218 056fe1ba 2003-11-23 devnull heapdel(VtBlock *b)
220 056fe1ba 2003-11-23 devnull int i, si;
221 056fe1ba 2003-11-23 devnull VtCache *c;
223 056fe1ba 2003-11-23 devnull c = b->c;
225 056fe1ba 2003-11-23 devnull si = b->heap;
226 056fe1ba 2003-11-23 devnull if(si == BadHeap)
228 056fe1ba 2003-11-23 devnull b->heap = BadHeap;
229 056fe1ba 2003-11-23 devnull c->nheap--;
230 056fe1ba 2003-11-23 devnull if(si == c->nheap)
232 056fe1ba 2003-11-23 devnull b = c->heap[c->nheap];
233 056fe1ba 2003-11-23 devnull i = upheap(si, b);
234 056fe1ba 2003-11-23 devnull if(i == si)
235 056fe1ba 2003-11-23 devnull downheap(i, b);
239 056fe1ba 2003-11-23 devnull * Insert a block into the heap.
240 056fe1ba 2003-11-23 devnull * Called with c->lk held.
242 056fe1ba 2003-11-23 devnull static void
243 056fe1ba 2003-11-23 devnull heapins(VtBlock *b)
245 056fe1ba 2003-11-23 devnull assert(b->heap == BadHeap);
246 056fe1ba 2003-11-23 devnull upheap(b->c->nheap++, b);
250 056fe1ba 2003-11-23 devnull * locate the vtBlock with the oldest second to last use.
251 056fe1ba 2003-11-23 devnull * remove it from the heap, and fix up the heap.
253 056fe1ba 2003-11-23 devnull /* called with c->lk held */
254 056fe1ba 2003-11-23 devnull static VtBlock*
255 056fe1ba 2003-11-23 devnull vtcachebumpblock(VtCache *c)
257 056fe1ba 2003-11-23 devnull VtBlock *b;
260 056fe1ba 2003-11-23 devnull * locate the vtBlock with the oldest second to last use.
261 056fe1ba 2003-11-23 devnull * remove it from the heap, and fix up the heap.
263 056fe1ba 2003-11-23 devnull if(c->nheap == 0){
264 056fe1ba 2003-11-23 devnull vtcachedump(c);
265 056fe1ba 2003-11-23 devnull abort();
266 056fe1ba 2003-11-23 devnull sysfatal("vtcachebumpblock: no free blocks in vtCache");
268 056fe1ba 2003-11-23 devnull b = c->heap[0];
269 056fe1ba 2003-11-23 devnull heapdel(b);
271 056fe1ba 2003-11-23 devnull assert(b->heap == BadHeap);
272 056fe1ba 2003-11-23 devnull assert(b->ref == 0);
275 056fe1ba 2003-11-23 devnull * unchain the vtBlock from hash chain if any
277 056fe1ba 2003-11-23 devnull if(b->prev){
278 056fe1ba 2003-11-23 devnull *(b->prev) = b->next;
279 056fe1ba 2003-11-23 devnull if(b->next)
280 056fe1ba 2003-11-23 devnull b->next->prev = b->prev;
281 056fe1ba 2003-11-23 devnull b->prev = nil;
285 056fe1ba 2003-11-23 devnull if(0)fprint(2, "droping %x:%V\n", b->addr, b->score);
286 056fe1ba 2003-11-23 devnull /* set vtBlock to a reasonable state */
287 056fe1ba 2003-11-23 devnull b->ref = 1;
288 056fe1ba 2003-11-23 devnull b->iostate = BioEmpty;
289 056fe1ba 2003-11-23 devnull return b;
293 056fe1ba 2003-11-23 devnull * fetch a local block from the memory cache.
294 056fe1ba 2003-11-23 devnull * if it's not there, load it, bumping some other Block.
295 056fe1ba 2003-11-23 devnull * if we're out of free blocks, we're screwed.
297 056fe1ba 2003-11-23 devnull VtBlock*
298 056fe1ba 2003-11-23 devnull vtcachelocal(VtCache *c, u32int addr, int type)
300 056fe1ba 2003-11-23 devnull VtBlock *b;
302 056fe1ba 2003-11-23 devnull if(addr >= c->nblock)
303 056fe1ba 2003-11-23 devnull sysfatal("vtcachelocal: asked for block #%ud; only %d blocks\n",
304 056fe1ba 2003-11-23 devnull addr, c->nblock);
306 056fe1ba 2003-11-23 devnull b = &c->block[addr];
307 056fe1ba 2003-11-23 devnull if(b->addr == NilBlock || b->iostate != BioLocal)
309 056fe1ba 2003-11-23 devnull abort();
310 056fe1ba 2003-11-23 devnull sysfatal("vtcachelocal: block is not local");
313 056fe1ba 2003-11-23 devnull if(b->type != type)
315 056fe1ba 2003-11-23 devnull print("%d != %d\n", b->type, type);
316 056fe1ba 2003-11-23 devnull abort();
317 056fe1ba 2003-11-23 devnull sysfatal("vtcachelocal: block has wrong type %d != %d", b->type, type);
320 056fe1ba 2003-11-23 devnull qlock(&c->lk);
321 056fe1ba 2003-11-23 devnull b->ref++;
322 056fe1ba 2003-11-23 devnull qunlock(&c->lk);
324 056fe1ba 2003-11-23 devnull qlock(&b->lk);
325 056fe1ba 2003-11-23 devnull b->nlock = 1;
326 056fe1ba 2003-11-23 devnull return b;
329 056fe1ba 2003-11-23 devnull VtBlock*
330 056fe1ba 2003-11-23 devnull vtcacheallocblock(VtCache *c, int type)
332 056fe1ba 2003-11-23 devnull VtBlock *b;
334 056fe1ba 2003-11-23 devnull if(type >= VtMaxType)
335 056fe1ba 2003-11-23 devnull abort();
337 056fe1ba 2003-11-23 devnull qlock(&c->lk);
338 056fe1ba 2003-11-23 devnull b = vtcachebumpblock(c);
339 056fe1ba 2003-11-23 devnull b->iostate = BioLocal;
340 056fe1ba 2003-11-23 devnull b->type = type;
341 056fe1ba 2003-11-23 devnull b->addr = b - c->block;
342 056fe1ba 2003-11-23 devnull vtzeroextend(type, b->data, 0, c->blocksize);
343 056fe1ba 2003-11-23 devnull vtlocaltoglobal(b->addr, b->score);
344 056fe1ba 2003-11-23 devnull qunlock(&c->lk);
346 056fe1ba 2003-11-23 devnull qlock(&b->lk);
347 056fe1ba 2003-11-23 devnull b->nlock = 1;
349 056fe1ba 2003-11-23 devnull return b;
353 056fe1ba 2003-11-23 devnull * fetch a global (Venti) block from the memory cache.
354 056fe1ba 2003-11-23 devnull * if it's not there, load it, bumping some other block.
356 056fe1ba 2003-11-23 devnull VtBlock*
357 056fe1ba 2003-11-23 devnull vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type)
359 056fe1ba 2003-11-23 devnull VtBlock *b;
360 056fe1ba 2003-11-23 devnull ulong h;
362 056fe1ba 2003-11-23 devnull u32int addr;
364 056fe1ba 2003-11-23 devnull addr = vtglobaltolocal(score);
365 056fe1ba 2003-11-23 devnull if(addr != NilBlock)
366 056fe1ba 2003-11-23 devnull return vtcachelocal(c, addr, type);
368 056fe1ba 2003-11-23 devnull h = (u32int)(score[0]|(score[1]<<8)|(score[2]<<16)|(score[3]<<24)) % c->nhash;
371 056fe1ba 2003-11-23 devnull * look for the block in the cache
373 056fe1ba 2003-11-23 devnull qlock(&c->lk);
374 056fe1ba 2003-11-23 devnull for(b = c->hash[h]; b != nil; b = b->next){
375 056fe1ba 2003-11-23 devnull if(b->addr != NilBlock || memcmp(b->score, score, VtScoreSize) != 0 || b->type != type)
376 056fe1ba 2003-11-23 devnull continue;
377 056fe1ba 2003-11-23 devnull heapdel(b);
378 056fe1ba 2003-11-23 devnull b->ref++;
379 056fe1ba 2003-11-23 devnull qunlock(&c->lk);
380 056fe1ba 2003-11-23 devnull qlock(&b->lk);
381 056fe1ba 2003-11-23 devnull b->nlock = 1;
382 056fe1ba 2003-11-23 devnull return b;
386 056fe1ba 2003-11-23 devnull * not found
388 056fe1ba 2003-11-23 devnull b = vtcachebumpblock(c);
389 056fe1ba 2003-11-23 devnull b->addr = NilBlock;
390 056fe1ba 2003-11-23 devnull b->type = type;
391 056fe1ba 2003-11-23 devnull memmove(b->score, score, VtScoreSize);
392 056fe1ba 2003-11-23 devnull /* chain onto correct hash */
393 056fe1ba 2003-11-23 devnull b->next = c->hash[h];
394 056fe1ba 2003-11-23 devnull c->hash[h] = b;
395 056fe1ba 2003-11-23 devnull if(b->next != nil)
396 056fe1ba 2003-11-23 devnull b->next->prev = &b->next;
397 056fe1ba 2003-11-23 devnull b->prev = &c->hash[h];
400 056fe1ba 2003-11-23 devnull * Lock b before unlocking c, so that others wait while we read.
402 056fe1ba 2003-11-23 devnull * You might think there is a race between this qlock(b) before qunlock(c)
403 056fe1ba 2003-11-23 devnull * and the qlock(c) while holding a qlock(b) in vtblockwrite. However,
404 056fe1ba 2003-11-23 devnull * the block here can never be the block in a vtblockwrite, so we're safe.
405 056fe1ba 2003-11-23 devnull * We're certainly living on the edge.
407 056fe1ba 2003-11-23 devnull qlock(&b->lk);
408 056fe1ba 2003-11-23 devnull b->nlock = 1;
409 056fe1ba 2003-11-23 devnull qunlock(&c->lk);
411 056fe1ba 2003-11-23 devnull n = vtread(c->z, score, type, b->data, c->blocksize);
412 056fe1ba 2003-11-23 devnull if(n < 0){
413 056fe1ba 2003-11-23 devnull fprint(2, "vtread: %r\n");
414 056fe1ba 2003-11-23 devnull b->iostate = BioVentiError;
415 056fe1ba 2003-11-23 devnull vtblockput(b);
416 056fe1ba 2003-11-23 devnull return nil;
418 056fe1ba 2003-11-23 devnull vtzeroextend(type, b->data, n, c->blocksize);
419 056fe1ba 2003-11-23 devnull b->iostate = BioVenti;
420 056fe1ba 2003-11-23 devnull b->nlock = 1;
421 056fe1ba 2003-11-23 devnull b->decrypted = 0;
422 056fe1ba 2003-11-23 devnull return b;
426 056fe1ba 2003-11-23 devnull * The thread that has locked b may refer to it by
427 056fe1ba 2003-11-23 devnull * multiple names. Nlock counts the number of
428 056fe1ba 2003-11-23 devnull * references the locking thread holds. It will call
429 056fe1ba 2003-11-23 devnull * vtblockput once per reference.
432 056fe1ba 2003-11-23 devnull vtblockduplock(VtBlock *b)
434 056fe1ba 2003-11-23 devnull assert(b->nlock > 0);
435 056fe1ba 2003-11-23 devnull b->nlock++;
439 056fe1ba 2003-11-23 devnull * we're done with the block.
440 056fe1ba 2003-11-23 devnull * unlock it. can't use it after calling this.
443 056fe1ba 2003-11-23 devnull vtblockput(VtBlock* b)
445 056fe1ba 2003-11-23 devnull VtCache *c;
447 056fe1ba 2003-11-23 devnull if(b == nil)
450 056fe1ba 2003-11-23 devnull if(0)fprint(2, "vtblockput: %d: %x %d %d\n", getpid(), b->addr, c->nheap, b->iostate);
452 056fe1ba 2003-11-23 devnull if(--b->nlock > 0)
456 056fe1ba 2003-11-23 devnull * b->nlock should probably stay at zero while
457 056fe1ba 2003-11-23 devnull * the vtBlock is unlocked, but diskThread and vtSleep
458 056fe1ba 2003-11-23 devnull * conspire to assume that they can just qlock(&b->lk); vtblockput(b),
459 056fe1ba 2003-11-23 devnull * so we have to keep b->nlock set to 1 even
460 056fe1ba 2003-11-23 devnull * when the vtBlock is unlocked.
462 056fe1ba 2003-11-23 devnull assert(b->nlock == 0);
463 056fe1ba 2003-11-23 devnull b->nlock = 1;
465 056fe1ba 2003-11-23 devnull qunlock(&b->lk);
466 056fe1ba 2003-11-23 devnull c = b->c;
467 056fe1ba 2003-11-23 devnull qlock(&c->lk);
469 056fe1ba 2003-11-23 devnull if(--b->ref > 0){
470 056fe1ba 2003-11-23 devnull qunlock(&c->lk);
474 056fe1ba 2003-11-23 devnull assert(b->ref == 0);
475 056fe1ba 2003-11-23 devnull switch(b->iostate){
476 056fe1ba 2003-11-23 devnull case BioVenti:
477 056fe1ba 2003-11-23 devnull //if(b->addr != NilBlock) print("blockput %d\n", b->addr);
478 056fe1ba 2003-11-23 devnull b->used = c->now++;
479 056fe1ba 2003-11-23 devnull case BioVentiError:
480 056fe1ba 2003-11-23 devnull heapins(b);
482 056fe1ba 2003-11-23 devnull case BioLocal:
485 056fe1ba 2003-11-23 devnull qunlock(&c->lk);
489 056fe1ba 2003-11-23 devnull vtblockwrite(VtBlock *b)
491 056fe1ba 2003-11-23 devnull uchar score[VtScoreSize];
492 056fe1ba 2003-11-23 devnull VtCache *c;
496 056fe1ba 2003-11-23 devnull if(b->iostate != BioLocal){
497 056fe1ba 2003-11-23 devnull abort();
498 056fe1ba 2003-11-23 devnull sysfatal("vtBlockWrite: not a local block");
501 056fe1ba 2003-11-23 devnull c = b->c;
502 056fe1ba 2003-11-23 devnull n = vtzerotruncate(b->type, b->data, c->blocksize);
503 056fe1ba 2003-11-23 devnull if(vtwrite(c->z, score, b->type, b->data, n) < 0)
504 056fe1ba 2003-11-23 devnull return -1;
506 056fe1ba 2003-11-23 devnull memmove(b->score, score, VtScoreSize);
508 056fe1ba 2003-11-23 devnull qlock(&c->lk);
509 056fe1ba 2003-11-23 devnull b->iostate = BioVenti;
510 056fe1ba 2003-11-23 devnull h = (u32int)(score[0]|(score[1]<<8)|(score[2]<<16)|(score[3]<<24)) % c->nhash;
511 056fe1ba 2003-11-23 devnull b->next = c->hash[h];
512 056fe1ba 2003-11-23 devnull c->hash[h] = b;
513 056fe1ba 2003-11-23 devnull if(b->next != nil)
514 056fe1ba 2003-11-23 devnull b->next->prev = &b->next;
515 056fe1ba 2003-11-23 devnull b->prev = &c->hash[h];
516 056fe1ba 2003-11-23 devnull qunlock(&c->lk);
517 056fe1ba 2003-11-23 devnull return 0;
521 056fe1ba 2003-11-23 devnull vtcacheblocksize(VtCache *c)
523 056fe1ba 2003-11-23 devnull return c->blocksize;
526 056fe1ba 2003-11-23 devnull VtBlock*
527 056fe1ba 2003-11-23 devnull vtblockcopy(VtBlock *b)
529 056fe1ba 2003-11-23 devnull VtBlock *bb;
531 056fe1ba 2003-11-23 devnull ncopy++;
532 056fe1ba 2003-11-23 devnull bb = vtcacheallocblock(b->c, b->type);
533 056fe1ba 2003-11-23 devnull if(bb == nil){
534 056fe1ba 2003-11-23 devnull vtblockput(b);
535 056fe1ba 2003-11-23 devnull return nil;
537 056fe1ba 2003-11-23 devnull memmove(bb->data, b->data, b->c->blocksize);
538 056fe1ba 2003-11-23 devnull vtblockput(b);
539 056fe1ba 2003-11-23 devnull return bb;
543 056fe1ba 2003-11-23 devnull vtlocaltoglobal(u32int addr, uchar score[VtScoreSize])
545 056fe1ba 2003-11-23 devnull memset(score, 0, 16);
546 056fe1ba 2003-11-23 devnull score[16] = addr>>24;
547 056fe1ba 2003-11-23 devnull score[17] = addr>>16;
548 056fe1ba 2003-11-23 devnull score[18] = addr>>8;
549 056fe1ba 2003-11-23 devnull score[19] = addr;
554 056fe1ba 2003-11-23 devnull vtglobaltolocal(uchar score[VtScoreSize])
556 056fe1ba 2003-11-23 devnull static uchar zero[16];
557 056fe1ba 2003-11-23 devnull if(memcmp(score, zero, 16) != 0)
558 056fe1ba 2003-11-23 devnull return NilBlock;
559 056fe1ba 2003-11-23 devnull return (score[16]<<24)|(score[17]<<16)|(score[18]<<8)|score[19];
563 d23a617a 2004-03-15 devnull vtblockdirty(VtBlock *b)
565 d23a617a 2004-03-15 devnull return 0;