1 7763a61a 2003-11-23 devnull #include "stdinc.h"
2 7763a61a 2003-11-23 devnull #include "vac.h"
3 7763a61a 2003-11-23 devnull #include "dat.h"
4 7763a61a 2003-11-23 devnull #include "fns.h"
5 7763a61a 2003-11-23 devnull #include "error.h"
7 7763a61a 2003-11-23 devnull static int sizeToDepth(uvlong s, int psize, int dsize);
9 7763a61a 2003-11-23 devnull static int
10 7763a61a 2003-11-23 devnull sizeToDepth(uvlong s, int psize, int dsize)
15 7763a61a 2003-11-23 devnull /* determine pointer depth */
16 7763a61a 2003-11-23 devnull np = psize/VtScoreSize;
17 7763a61a 2003-11-23 devnull s = (s + dsize - 1)/dsize;
18 7763a61a 2003-11-23 devnull for(d = 0; s > 1; d++)
19 7763a61a 2003-11-23 devnull s = (s + np - 1)/np;
20 7763a61a 2003-11-23 devnull return d;
23 7763a61a 2003-11-23 devnull /* assumes u is lock? */
25 7763a61a 2003-11-23 devnull sourceAlloc(Cache *c, Lump *u, ulong block, int entry, int readOnly)
27 7763a61a 2003-11-23 devnull Source *r;
28 7763a61a 2003-11-23 devnull VtEntry d;
30 7763a61a 2003-11-23 devnull if(u->asize < (entry+1)*VtEntrySize) {
31 7763a61a 2003-11-23 devnull vtSetError(ENoDir);
32 7763a61a 2003-11-23 devnull return nil;
35 7763a61a 2003-11-23 devnull if(!vtEntryUnpack(&d, u->data, entry))
36 7763a61a 2003-11-23 devnull return nil;
38 7763a61a 2003-11-23 devnull if(!(d.flags & VtEntryActive)) {
39 7763a61a 2003-11-23 devnull fprint(2, "bad flags %#ux %V\n", d.flags, d.score);
40 7763a61a 2003-11-23 devnull vtSetError(ENoDir);
41 7763a61a 2003-11-23 devnull return nil;
44 7763a61a 2003-11-23 devnull /* HACK for backwards compatiblity - should go away at some point */
45 7763a61a 2003-11-23 devnull if(d.depth == 0) {
46 7763a61a 2003-11-23 devnull if(d.size > d.dsize) fprint(2, "depth == 0! size = %ulld\n", d.size);
47 7763a61a 2003-11-23 devnull d.depth = sizeToDepth(d.size, d.psize, d.dsize);
50 7763a61a 2003-11-23 devnull if(d.depth < sizeToDepth(d.size, d.psize, d.dsize)) {
51 7763a61a 2003-11-23 devnull vtSetError(EBadDir);
52 7763a61a 2003-11-23 devnull return nil;
55 7763a61a 2003-11-23 devnull r = vtMemAllocZ(sizeof(Source));
56 7763a61a 2003-11-23 devnull r->lk = vtLockAlloc();
57 7763a61a 2003-11-23 devnull r->cache = c;
58 7763a61a 2003-11-23 devnull r->readOnly = readOnly;
59 7763a61a 2003-11-23 devnull r->lump = lumpIncRef(u);
60 7763a61a 2003-11-23 devnull r->block = block;
61 7763a61a 2003-11-23 devnull r->entry = entry;
62 7763a61a 2003-11-23 devnull r->gen = d.gen;
63 7763a61a 2003-11-23 devnull r->dir = (d.flags & VtEntryDir) != 0;
64 7763a61a 2003-11-23 devnull r->depth = d.depth;
65 7763a61a 2003-11-23 devnull r->psize = d.psize;
66 7763a61a 2003-11-23 devnull r->dsize = d.dsize;
67 7763a61a 2003-11-23 devnull r->size = d.size;
69 7763a61a 2003-11-23 devnull r->epb = r->dsize/VtEntrySize;
71 7763a61a 2003-11-23 devnull return r;
75 7763a61a 2003-11-23 devnull sourceOpen(Source *r, ulong entry, int readOnly)
77 7763a61a 2003-11-23 devnull ulong bn;
80 7763a61a 2003-11-23 devnull if(0)fprint(2, "sourceOpen: %V:%d: %lud\n", r->lump->score, r->entry, entry);
81 7763a61a 2003-11-23 devnull if(r->readOnly && !readOnly) {
82 7763a61a 2003-11-23 devnull vtSetError(EReadOnly);
83 7763a61a 2003-11-23 devnull return nil;
86 7763a61a 2003-11-23 devnull bn = entry/r->epb;
88 7763a61a 2003-11-23 devnull u = sourceGetLump(r, bn, readOnly, 1);
89 7763a61a 2003-11-23 devnull if(u == nil)
90 7763a61a 2003-11-23 devnull return nil;
92 7763a61a 2003-11-23 devnull r = sourceAlloc(r->cache, u, bn, entry%r->epb, readOnly);
93 7763a61a 2003-11-23 devnull lumpDecRef(u, 1);
94 7763a61a 2003-11-23 devnull return r;
98 7763a61a 2003-11-23 devnull sourceCreate(Source *r, int psize, int dsize, int isdir, ulong entry)
100 7763a61a 2003-11-23 devnull Source *rr;
102 7763a61a 2003-11-23 devnull Lump *u;
103 7763a61a 2003-11-23 devnull ulong bn;
104 7763a61a 2003-11-23 devnull VtEntry dir;
106 7763a61a 2003-11-23 devnull if(r->readOnly) {
107 7763a61a 2003-11-23 devnull vtSetError(EReadOnly);
108 7763a61a 2003-11-23 devnull return nil;
111 7763a61a 2003-11-23 devnull if(entry == 0) {
113 7763a61a 2003-11-23 devnull * look at a random block to see if we can find an empty entry
115 7763a61a 2003-11-23 devnull entry = sourceGetDirSize(r);
116 7763a61a 2003-11-23 devnull entry = r->epb*lnrand(entry/r->epb+1);
120 7763a61a 2003-11-23 devnull * need to loop since multiple threads could be trying to allocate
122 7763a61a 2003-11-23 devnull for(;;) {
123 7763a61a 2003-11-23 devnull bn = entry/r->epb;
124 7763a61a 2003-11-23 devnull sourceSetDepth(r, (uvlong)(bn+1)*r->dsize);
125 7763a61a 2003-11-23 devnull u = sourceGetLump(r, bn, 0, 1);
126 7763a61a 2003-11-23 devnull if(u == nil)
127 7763a61a 2003-11-23 devnull return nil;
128 7763a61a 2003-11-23 devnull for(i=entry%r->epb; i<r->epb; i++) {
129 7763a61a 2003-11-23 devnull vtEntryUnpack(&dir, u->data, i);
130 7763a61a 2003-11-23 devnull if((dir.flags&VtEntryActive) == 0 && dir.gen != ~0)
131 7763a61a 2003-11-23 devnull goto Found;
133 7763a61a 2003-11-23 devnull lumpDecRef(u, 1);
134 7763a61a 2003-11-23 devnull entry = sourceGetDirSize(r);
137 7763a61a 2003-11-23 devnull /* found an entry */
138 7763a61a 2003-11-23 devnull dir.psize = psize;
139 7763a61a 2003-11-23 devnull dir.dsize = dsize;
140 7763a61a 2003-11-23 devnull dir.flags = VtEntryActive;
141 7763a61a 2003-11-23 devnull if(isdir)
142 7763a61a 2003-11-23 devnull dir.flags |= VtEntryDir;
143 7763a61a 2003-11-23 devnull dir.depth = 0;
144 7763a61a 2003-11-23 devnull dir.size = 0;
145 7763a61a 2003-11-23 devnull memmove(dir.score, vtZeroScore, VtScoreSize);
146 7763a61a 2003-11-23 devnull vtEntryPack(&dir, u->data, i);
148 7763a61a 2003-11-23 devnull sourceSetDirSize(r, bn*r->epb + i + 1);
149 7763a61a 2003-11-23 devnull rr = sourceAlloc(r->cache, u, bn, i, 0);
151 7763a61a 2003-11-23 devnull lumpDecRef(u, 1);
152 7763a61a 2003-11-23 devnull return rr;
156 7763a61a 2003-11-23 devnull sourceRemove(Source *r)
158 7763a61a 2003-11-23 devnull lumpFreeEntry(r->lump, r->entry);
159 7763a61a 2003-11-23 devnull sourceFree(r);
163 7763a61a 2003-11-23 devnull sourceSetDepth(Source *r, uvlong size)
165 7763a61a 2003-11-23 devnull Lump *u, *v;
166 7763a61a 2003-11-23 devnull VtEntry dir;
167 7763a61a 2003-11-23 devnull int depth;
169 7763a61a 2003-11-23 devnull if(r->readOnly){
170 7763a61a 2003-11-23 devnull vtSetError(EReadOnly);
171 7763a61a 2003-11-23 devnull return 0;
174 7763a61a 2003-11-23 devnull depth = sizeToDepth(size, r->psize, r->dsize);
176 7763a61a 2003-11-23 devnull assert(depth >= 0);
178 7763a61a 2003-11-23 devnull if(depth > VtPointerDepth) {
179 7763a61a 2003-11-23 devnull vtSetError(ETooBig);
180 7763a61a 2003-11-23 devnull return 0;
183 7763a61a 2003-11-23 devnull vtLock(r->lk);
185 7763a61a 2003-11-23 devnull if(r->depth >= depth) {
186 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
187 7763a61a 2003-11-23 devnull return 1;
190 7763a61a 2003-11-23 devnull u = r->lump;
191 7763a61a 2003-11-23 devnull vtLock(u->lk);
192 7763a61a 2003-11-23 devnull if(!vtEntryUnpack(&dir, u->data, r->entry)) {
193 7763a61a 2003-11-23 devnull vtUnlock(u->lk);
194 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
195 7763a61a 2003-11-23 devnull return 0;
197 7763a61a 2003-11-23 devnull while(dir.depth < depth) {
198 7763a61a 2003-11-23 devnull v = cacheAllocLump(r->cache, VtPointerType0+r->depth, r->psize, r->dir);
199 7763a61a 2003-11-23 devnull if(v == nil)
201 7763a61a 2003-11-23 devnull memmove(v->data, dir.score, VtScoreSize);
202 7763a61a 2003-11-23 devnull memmove(dir.score, v->score, VtScoreSize);
203 7763a61a 2003-11-23 devnull dir.depth++;
204 7763a61a 2003-11-23 devnull vtUnlock(v->lk);
206 7763a61a 2003-11-23 devnull vtEntryPack(&dir, u->data, r->entry);
207 7763a61a 2003-11-23 devnull vtUnlock(u->lk);
209 7763a61a 2003-11-23 devnull r->depth = dir.depth;
210 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
212 7763a61a 2003-11-23 devnull return dir.depth == depth;
216 7763a61a 2003-11-23 devnull sourceGetVtEntry(Source *r, VtEntry *dir)
218 7763a61a 2003-11-23 devnull Lump *u;
220 7763a61a 2003-11-23 devnull u = r->lump;
221 7763a61a 2003-11-23 devnull vtLock(u->lk);
222 7763a61a 2003-11-23 devnull if(!vtEntryUnpack(dir, u->data, r->entry)) {
223 7763a61a 2003-11-23 devnull vtUnlock(u->lk);
224 7763a61a 2003-11-23 devnull return 0;
226 7763a61a 2003-11-23 devnull vtUnlock(u->lk);
227 7763a61a 2003-11-23 devnull return 1;
231 7763a61a 2003-11-23 devnull sourceGetSize(Source *r)
233 7763a61a 2003-11-23 devnull uvlong size;
235 7763a61a 2003-11-23 devnull vtLock(r->lk);
236 7763a61a 2003-11-23 devnull size = r->size;
237 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
239 7763a61a 2003-11-23 devnull return size;
244 7763a61a 2003-11-23 devnull sourceSetSize(Source *r, uvlong size)
246 7763a61a 2003-11-23 devnull Lump *u;
247 7763a61a 2003-11-23 devnull VtEntry dir;
248 7763a61a 2003-11-23 devnull int depth;
250 7763a61a 2003-11-23 devnull if(r->readOnly) {
251 7763a61a 2003-11-23 devnull vtSetError(EReadOnly);
252 7763a61a 2003-11-23 devnull return 0;
255 7763a61a 2003-11-23 devnull if(size > VtMaxFileSize || size > ((uvlong)MaxBlock)*r->dsize) {
256 7763a61a 2003-11-23 devnull vtSetError(ETooBig);
257 7763a61a 2003-11-23 devnull return 0;
260 7763a61a 2003-11-23 devnull vtLock(r->lk);
261 7763a61a 2003-11-23 devnull depth = sizeToDepth(size, r->psize, r->dsize);
262 7763a61a 2003-11-23 devnull if(size < r->size) {
263 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
264 7763a61a 2003-11-23 devnull return 1;
266 7763a61a 2003-11-23 devnull if(depth > r->depth) {
267 7763a61a 2003-11-23 devnull vtSetError(EBadDir);
268 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
269 7763a61a 2003-11-23 devnull return 0;
272 7763a61a 2003-11-23 devnull u = r->lump;
273 7763a61a 2003-11-23 devnull vtLock(u->lk);
274 7763a61a 2003-11-23 devnull vtEntryUnpack(&dir, u->data, r->entry);
275 7763a61a 2003-11-23 devnull dir.size = size;
276 7763a61a 2003-11-23 devnull vtEntryPack(&dir, u->data, r->entry);
277 7763a61a 2003-11-23 devnull vtUnlock(u->lk);
278 7763a61a 2003-11-23 devnull r->size = size;
279 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
280 7763a61a 2003-11-23 devnull return 1;
284 7763a61a 2003-11-23 devnull sourceSetDirSize(Source *r, ulong ds)
286 7763a61a 2003-11-23 devnull uvlong size;
288 7763a61a 2003-11-23 devnull size = (uvlong)r->dsize*(ds/r->epb);
289 7763a61a 2003-11-23 devnull size += VtEntrySize*(ds%r->epb);
290 7763a61a 2003-11-23 devnull return sourceSetSize(r, size);
294 7763a61a 2003-11-23 devnull sourceGetDirSize(Source *r)
296 7763a61a 2003-11-23 devnull ulong ds;
297 7763a61a 2003-11-23 devnull uvlong size;
299 7763a61a 2003-11-23 devnull size = sourceGetSize(r);
300 7763a61a 2003-11-23 devnull ds = r->epb*(size/r->dsize);
301 7763a61a 2003-11-23 devnull ds += (size%r->dsize)/VtEntrySize;
302 7763a61a 2003-11-23 devnull return ds;
306 7763a61a 2003-11-23 devnull sourceGetNumBlocks(Source *r)
308 7763a61a 2003-11-23 devnull return (sourceGetSize(r)+r->dsize-1)/r->dsize;
312 7763a61a 2003-11-23 devnull sourceWalk(Source *r, ulong block, int readOnly, int *off)
314 7763a61a 2003-11-23 devnull int depth;
315 7763a61a 2003-11-23 devnull int i, np;
316 7763a61a 2003-11-23 devnull Lump *u, *v;
317 7763a61a 2003-11-23 devnull int elem[VtPointerDepth+1];
318 7763a61a 2003-11-23 devnull ulong b;
320 7763a61a 2003-11-23 devnull if(r->readOnly && !readOnly) {
321 7763a61a 2003-11-23 devnull vtSetError(EReadOnly);
322 7763a61a 2003-11-23 devnull return nil;
325 7763a61a 2003-11-23 devnull vtLock(r->lk);
326 7763a61a 2003-11-23 devnull np = r->psize/VtScoreSize;
327 7763a61a 2003-11-23 devnull b = block;
328 7763a61a 2003-11-23 devnull for(i=0; i<r->depth; i++) {
329 7763a61a 2003-11-23 devnull elem[i] = b % np;
330 7763a61a 2003-11-23 devnull b /= np;
332 7763a61a 2003-11-23 devnull if(b != 0) {
333 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
334 7763a61a 2003-11-23 devnull vtSetError(EBadOffset);
335 7763a61a 2003-11-23 devnull return nil;
337 7763a61a 2003-11-23 devnull elem[i] = r->entry;
338 7763a61a 2003-11-23 devnull u = lumpIncRef(r->lump);
339 7763a61a 2003-11-23 devnull depth = r->depth;
340 7763a61a 2003-11-23 devnull *off = elem[0];
341 7763a61a 2003-11-23 devnull vtUnlock(r->lk);
343 7763a61a 2003-11-23 devnull for(i=depth; i>0; i--) {
344 7763a61a 2003-11-23 devnull v = lumpWalk(u, elem[i], VtPointerType0+i-1, r->psize, readOnly, 0);
345 7763a61a 2003-11-23 devnull lumpDecRef(u, 0);
346 7763a61a 2003-11-23 devnull if(v == nil)
347 7763a61a 2003-11-23 devnull return nil;
351 7763a61a 2003-11-23 devnull return u;
355 7763a61a 2003-11-23 devnull sourceGetLump(Source *r, ulong block, int readOnly, int lock)
357 7763a61a 2003-11-23 devnull int type, off;
358 7763a61a 2003-11-23 devnull Lump *u, *v;
360 7763a61a 2003-11-23 devnull if(r->readOnly && !readOnly) {
361 7763a61a 2003-11-23 devnull vtSetError(EReadOnly);
362 7763a61a 2003-11-23 devnull return nil;
364 7763a61a 2003-11-23 devnull if(block == NilBlock) {
365 7763a61a 2003-11-23 devnull vtSetError(ENilBlock);
366 7763a61a 2003-11-23 devnull return nil;
368 7763a61a 2003-11-23 devnull if(0)fprint(2, "sourceGetLump: %V:%d %lud\n", r->lump->score, r->entry, block);
369 7763a61a 2003-11-23 devnull u = sourceWalk(r, block, readOnly, &off);
370 7763a61a 2003-11-23 devnull if(u == nil)
371 7763a61a 2003-11-23 devnull return nil;
372 7763a61a 2003-11-23 devnull if(r->dir)
373 7763a61a 2003-11-23 devnull type = VtDirType;
375 7763a61a 2003-11-23 devnull type = VtDataType;
376 7763a61a 2003-11-23 devnull v = lumpWalk(u, off, type, r->dsize, readOnly, lock);
377 7763a61a 2003-11-23 devnull lumpDecRef(u, 0);
378 7763a61a 2003-11-23 devnull return v;
382 7763a61a 2003-11-23 devnull sourceFree(Source *k)
384 7763a61a 2003-11-23 devnull if(k == nil)
386 7763a61a 2003-11-23 devnull lumpDecRef(k->lump, 0);
387 7763a61a 2003-11-23 devnull vtLockFree(k->lk);
388 7763a61a 2003-11-23 devnull memset(k, ~0, sizeof(*k));
389 7763a61a 2003-11-23 devnull vtMemFree(k);