Blame


1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
2 6f4d00ee 2013-09-23 0intro #include "dat.h"
3 6f4d00ee 2013-09-23 0intro #include "fns.h"
4 6f4d00ee 2013-09-23 0intro #include "error.h"
5 6f4d00ee 2013-09-23 0intro #include "9.h"
6 6f4d00ee 2013-09-23 0intro
7 6f4d00ee 2013-09-23 0intro static int sizeToDepth(uvlong s, int psize, int dsize);
8 6f4d00ee 2013-09-23 0intro static u32int tagGen(void);
9 6f4d00ee 2013-09-23 0intro static Block *sourceLoad(Source *r, Entry *e);
10 6f4d00ee 2013-09-23 0intro static int sourceShrinkDepth(Source*, Block*, Entry*, int);
11 6f4d00ee 2013-09-23 0intro static int sourceShrinkSize(Source*, Entry*, uvlong);
12 6f4d00ee 2013-09-23 0intro static int sourceGrowDepth(Source*, Block*, Entry*, int);
13 6f4d00ee 2013-09-23 0intro
14 6f4d00ee 2013-09-23 0intro #define sourceIsLocked(r) ((r)->b != nil)
15 6f4d00ee 2013-09-23 0intro
16 6f4d00ee 2013-09-23 0intro static Source *
17 6f4d00ee 2013-09-23 0intro sourceAlloc(Fs *fs, Block *b, Source *p, u32int offset, int mode, int issnapshot)
18 6f4d00ee 2013-09-23 0intro {
19 6f4d00ee 2013-09-23 0intro int epb;
20 6f4d00ee 2013-09-23 0intro u32int epoch;
21 6f4d00ee 2013-09-23 0intro char *pname = nil;
22 6f4d00ee 2013-09-23 0intro Source *r;
23 6f4d00ee 2013-09-23 0intro Entry e;
24 6f4d00ee 2013-09-23 0intro
25 6f4d00ee 2013-09-23 0intro assert(p==nil || sourceIsLocked(p));
26 6f4d00ee 2013-09-23 0intro
27 6f4d00ee 2013-09-23 0intro if(p == nil){
28 6f4d00ee 2013-09-23 0intro assert(offset == 0);
29 6f4d00ee 2013-09-23 0intro epb = 1;
30 6f4d00ee 2013-09-23 0intro }else
31 6f4d00ee 2013-09-23 0intro epb = p->dsize / VtEntrySize;
32 6f4d00ee 2013-09-23 0intro
33 6f4d00ee 2013-09-23 0intro if(b->l.type != BtDir)
34 6f4d00ee 2013-09-23 0intro goto Bad;
35 6f4d00ee 2013-09-23 0intro
36 6f4d00ee 2013-09-23 0intro /*
37 6f4d00ee 2013-09-23 0intro * a non-active entry is the only thing that
38 6f4d00ee 2013-09-23 0intro * can legitimately happen here. all the others
39 6f4d00ee 2013-09-23 0intro * get prints.
40 6f4d00ee 2013-09-23 0intro */
41 6f4d00ee 2013-09-23 0intro if(!entryUnpack(&e, b->data, offset % epb)){
42 6f4d00ee 2013-09-23 0intro pname = sourceName(p);
43 6f4d00ee 2013-09-23 0intro consPrint("%s: %s %V: sourceAlloc: entryUnpack failed\n",
44 6f4d00ee 2013-09-23 0intro fs->name, pname, b->score);
45 6f4d00ee 2013-09-23 0intro goto Bad;
46 6f4d00ee 2013-09-23 0intro }
47 6f4d00ee 2013-09-23 0intro if(!(e.flags & VtEntryActive)){
48 6f4d00ee 2013-09-23 0intro pname = sourceName(p);
49 6f4d00ee 2013-09-23 0intro if(0) consPrint("%s: %s %V: sourceAlloc: not active\n",
50 6f4d00ee 2013-09-23 0intro fs->name, pname, e.score);
51 6f4d00ee 2013-09-23 0intro goto Bad;
52 6f4d00ee 2013-09-23 0intro }
53 6f4d00ee 2013-09-23 0intro if(e.psize < 256 || e.dsize < 256){
54 6f4d00ee 2013-09-23 0intro pname = sourceName(p);
55 6f4d00ee 2013-09-23 0intro consPrint("%s: %s %V: sourceAlloc: psize %ud or dsize %ud < 256\n",
56 6f4d00ee 2013-09-23 0intro fs->name, pname, e.score, e.psize, e.dsize);
57 6f4d00ee 2013-09-23 0intro goto Bad;
58 6f4d00ee 2013-09-23 0intro }
59 6f4d00ee 2013-09-23 0intro
60 6f4d00ee 2013-09-23 0intro if(e.depth < sizeToDepth(e.size, e.psize, e.dsize)){
61 6f4d00ee 2013-09-23 0intro pname = sourceName(p);
62 6f4d00ee 2013-09-23 0intro consPrint("%s: %s %V: sourceAlloc: depth %ud size %llud "
63 6f4d00ee 2013-09-23 0intro "psize %ud dsize %ud\n", fs->name, pname,
64 6f4d00ee 2013-09-23 0intro e.score, e.depth, e.size, e.psize, e.dsize);
65 6f4d00ee 2013-09-23 0intro goto Bad;
66 6f4d00ee 2013-09-23 0intro }
67 6f4d00ee 2013-09-23 0intro
68 6f4d00ee 2013-09-23 0intro if((e.flags & VtEntryLocal) && e.tag == 0){
69 6f4d00ee 2013-09-23 0intro pname = sourceName(p);
70 6f4d00ee 2013-09-23 0intro consPrint("%s: %s %V: sourceAlloc: flags %#ux tag %#ux\n",
71 6f4d00ee 2013-09-23 0intro fs->name, pname, e.score, e.flags, e.tag);
72 6f4d00ee 2013-09-23 0intro goto Bad;
73 6f4d00ee 2013-09-23 0intro }
74 6f4d00ee 2013-09-23 0intro
75 6f4d00ee 2013-09-23 0intro if(e.dsize > fs->blockSize || e.psize > fs->blockSize){
76 6f4d00ee 2013-09-23 0intro pname = sourceName(p);
77 6f4d00ee 2013-09-23 0intro consPrint("%s: %s %V: sourceAlloc: psize %ud or dsize %ud "
78 6f4d00ee 2013-09-23 0intro "> blocksize %ud\n", fs->name, pname, e.score,
79 6f4d00ee 2013-09-23 0intro e.psize, e.dsize, fs->blockSize);
80 6f4d00ee 2013-09-23 0intro goto Bad;
81 6f4d00ee 2013-09-23 0intro }
82 6f4d00ee 2013-09-23 0intro
83 6f4d00ee 2013-09-23 0intro epoch = b->l.epoch;
84 6f4d00ee 2013-09-23 0intro if(mode == OReadWrite){
85 6f4d00ee 2013-09-23 0intro if(e.snap != 0){
86 4b576658 2013-09-23 0intro werrstr(ESnapRO);
87 6f4d00ee 2013-09-23 0intro return nil;
88 6f4d00ee 2013-09-23 0intro }
89 6f4d00ee 2013-09-23 0intro }else if(e.snap != 0){
90 6f4d00ee 2013-09-23 0intro if(e.snap < fs->elo){
91 4b576658 2013-09-23 0intro werrstr(ESnapOld);
92 6f4d00ee 2013-09-23 0intro return nil;
93 6f4d00ee 2013-09-23 0intro }
94 6f4d00ee 2013-09-23 0intro if(e.snap >= fs->ehi)
95 6f4d00ee 2013-09-23 0intro goto Bad;
96 6f4d00ee 2013-09-23 0intro epoch = e.snap;
97 6f4d00ee 2013-09-23 0intro }
98 6f4d00ee 2013-09-23 0intro
99 4b576658 2013-09-23 0intro r = vtmallocz(sizeof(Source));
100 6f4d00ee 2013-09-23 0intro r->fs = fs;
101 6f4d00ee 2013-09-23 0intro r->mode = mode;
102 6f4d00ee 2013-09-23 0intro r->issnapshot = issnapshot;
103 6f4d00ee 2013-09-23 0intro r->dsize = e.dsize;
104 6f4d00ee 2013-09-23 0intro r->gen = e.gen;
105 4b576658 2013-09-23 0intro r->dir = (e.flags & _VtEntryDir) != 0;
106 6f4d00ee 2013-09-23 0intro r->ref = 1;
107 6f4d00ee 2013-09-23 0intro r->parent = p;
108 6f4d00ee 2013-09-23 0intro if(p){
109 4b576658 2013-09-23 0intro qlock(&p->lk);
110 6f4d00ee 2013-09-23 0intro assert(mode == OReadOnly || p->mode == OReadWrite);
111 6f4d00ee 2013-09-23 0intro p->ref++;
112 4b576658 2013-09-23 0intro qunlock(&p->lk);
113 6f4d00ee 2013-09-23 0intro }
114 6f4d00ee 2013-09-23 0intro r->epoch = epoch;
115 6f4d00ee 2013-09-23 0intro // consPrint("sourceAlloc: have %V be.%d fse.%d %s\n", b->score,
116 6f4d00ee 2013-09-23 0intro // b->l.epoch, r->fs->ehi, mode == OReadWrite? "rw": "ro");
117 6f4d00ee 2013-09-23 0intro memmove(r->score, b->score, VtScoreSize);
118 6f4d00ee 2013-09-23 0intro r->scoreEpoch = b->l.epoch;
119 6f4d00ee 2013-09-23 0intro r->offset = offset;
120 6f4d00ee 2013-09-23 0intro r->epb = epb;
121 6f4d00ee 2013-09-23 0intro r->tag = b->l.tag;
122 6f4d00ee 2013-09-23 0intro
123 6f4d00ee 2013-09-23 0intro // consPrint("%s: sourceAlloc: %p -> %V %d\n", r, r->score, r->offset);
124 6f4d00ee 2013-09-23 0intro
125 6f4d00ee 2013-09-23 0intro return r;
126 6f4d00ee 2013-09-23 0intro Bad:
127 6f4d00ee 2013-09-23 0intro free(pname);
128 4b576658 2013-09-23 0intro werrstr(EBadEntry);
129 6f4d00ee 2013-09-23 0intro return nil;
130 6f4d00ee 2013-09-23 0intro }
131 6f4d00ee 2013-09-23 0intro
132 6f4d00ee 2013-09-23 0intro Source *
133 6f4d00ee 2013-09-23 0intro sourceRoot(Fs *fs, u32int addr, int mode)
134 6f4d00ee 2013-09-23 0intro {
135 6f4d00ee 2013-09-23 0intro Source *r;
136 6f4d00ee 2013-09-23 0intro Block *b;
137 6f4d00ee 2013-09-23 0intro
138 6f4d00ee 2013-09-23 0intro b = cacheLocalData(fs->cache, addr, BtDir, RootTag, mode, 0);
139 6f4d00ee 2013-09-23 0intro if(b == nil)
140 6f4d00ee 2013-09-23 0intro return nil;
141 6f4d00ee 2013-09-23 0intro
142 6f4d00ee 2013-09-23 0intro if(mode == OReadWrite && b->l.epoch != fs->ehi){
143 6f4d00ee 2013-09-23 0intro consPrint("sourceRoot: fs->ehi = %ud, b->l = %L\n",
144 6f4d00ee 2013-09-23 0intro fs->ehi, &b->l);
145 6f4d00ee 2013-09-23 0intro blockPut(b);
146 4b576658 2013-09-23 0intro werrstr(EBadRoot);
147 6f4d00ee 2013-09-23 0intro return nil;
148 6f4d00ee 2013-09-23 0intro }
149 6f4d00ee 2013-09-23 0intro
150 6f4d00ee 2013-09-23 0intro r = sourceAlloc(fs, b, nil, 0, mode, 0);
151 6f4d00ee 2013-09-23 0intro blockPut(b);
152 6f4d00ee 2013-09-23 0intro return r;
153 6f4d00ee 2013-09-23 0intro }
154 6f4d00ee 2013-09-23 0intro
155 6f4d00ee 2013-09-23 0intro Source *
156 6f4d00ee 2013-09-23 0intro sourceOpen(Source *r, ulong offset, int mode, int issnapshot)
157 6f4d00ee 2013-09-23 0intro {
158 6f4d00ee 2013-09-23 0intro ulong bn;
159 6f4d00ee 2013-09-23 0intro Block *b;
160 6f4d00ee 2013-09-23 0intro
161 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
162 6f4d00ee 2013-09-23 0intro if(r->mode == OReadWrite)
163 6f4d00ee 2013-09-23 0intro assert(r->epoch == r->b->l.epoch);
164 6f4d00ee 2013-09-23 0intro if(!r->dir){
165 4b576658 2013-09-23 0intro werrstr(ENotDir);
166 6f4d00ee 2013-09-23 0intro return nil;
167 6f4d00ee 2013-09-23 0intro }
168 6f4d00ee 2013-09-23 0intro
169 6f4d00ee 2013-09-23 0intro bn = offset/(r->dsize/VtEntrySize);
170 6f4d00ee 2013-09-23 0intro
171 6f4d00ee 2013-09-23 0intro b = sourceBlock(r, bn, mode);
172 6f4d00ee 2013-09-23 0intro if(b == nil)
173 6f4d00ee 2013-09-23 0intro return nil;
174 6f4d00ee 2013-09-23 0intro r = sourceAlloc(r->fs, b, r, offset, mode, issnapshot);
175 6f4d00ee 2013-09-23 0intro blockPut(b);
176 6f4d00ee 2013-09-23 0intro return r;
177 6f4d00ee 2013-09-23 0intro }
178 6f4d00ee 2013-09-23 0intro
179 6f4d00ee 2013-09-23 0intro Source *
180 6f4d00ee 2013-09-23 0intro sourceCreate(Source *r, int dsize, int dir, u32int offset)
181 6f4d00ee 2013-09-23 0intro {
182 6f4d00ee 2013-09-23 0intro int i, epb, psize;
183 6f4d00ee 2013-09-23 0intro u32int bn, size;
184 6f4d00ee 2013-09-23 0intro Block *b;
185 6f4d00ee 2013-09-23 0intro Entry e;
186 6f4d00ee 2013-09-23 0intro Source *rr;
187 6f4d00ee 2013-09-23 0intro
188 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
189 6f4d00ee 2013-09-23 0intro
190 6f4d00ee 2013-09-23 0intro if(!r->dir){
191 4b576658 2013-09-23 0intro werrstr(ENotDir);
192 6f4d00ee 2013-09-23 0intro return nil;
193 6f4d00ee 2013-09-23 0intro }
194 6f4d00ee 2013-09-23 0intro
195 6f4d00ee 2013-09-23 0intro epb = r->dsize/VtEntrySize;
196 6f4d00ee 2013-09-23 0intro psize = (dsize/VtScoreSize)*VtScoreSize;
197 6f4d00ee 2013-09-23 0intro
198 6f4d00ee 2013-09-23 0intro size = sourceGetDirSize(r);
199 6f4d00ee 2013-09-23 0intro if(offset == 0){
200 6f4d00ee 2013-09-23 0intro /*
201 6f4d00ee 2013-09-23 0intro * look at a random block to see if we can find an empty entry
202 6f4d00ee 2013-09-23 0intro */
203 6f4d00ee 2013-09-23 0intro offset = lnrand(size+1);
204 6f4d00ee 2013-09-23 0intro offset -= offset % epb;
205 6f4d00ee 2013-09-23 0intro }
206 6f4d00ee 2013-09-23 0intro
207 6f4d00ee 2013-09-23 0intro /* try the given block and then try the last block */
208 6f4d00ee 2013-09-23 0intro for(;;){
209 6f4d00ee 2013-09-23 0intro bn = offset/epb;
210 6f4d00ee 2013-09-23 0intro b = sourceBlock(r, bn, OReadWrite);
211 6f4d00ee 2013-09-23 0intro if(b == nil)
212 6f4d00ee 2013-09-23 0intro return nil;
213 6f4d00ee 2013-09-23 0intro for(i=offset%r->epb; i<epb; i++){
214 6f4d00ee 2013-09-23 0intro entryUnpack(&e, b->data, i);
215 6f4d00ee 2013-09-23 0intro if((e.flags&VtEntryActive) == 0 && e.gen != ~0)
216 6f4d00ee 2013-09-23 0intro goto Found;
217 6f4d00ee 2013-09-23 0intro }
218 6f4d00ee 2013-09-23 0intro blockPut(b);
219 6f4d00ee 2013-09-23 0intro if(offset == size){
220 6f4d00ee 2013-09-23 0intro fprint(2, "sourceCreate: cannot happen\n");
221 4b576658 2013-09-23 0intro werrstr("sourceCreate: cannot happen");
222 6f4d00ee 2013-09-23 0intro return nil;
223 6f4d00ee 2013-09-23 0intro }
224 6f4d00ee 2013-09-23 0intro offset = size;
225 6f4d00ee 2013-09-23 0intro }
226 6f4d00ee 2013-09-23 0intro
227 6f4d00ee 2013-09-23 0intro Found:
228 6f4d00ee 2013-09-23 0intro /* found an entry - gen already set */
229 6f4d00ee 2013-09-23 0intro e.psize = psize;
230 6f4d00ee 2013-09-23 0intro e.dsize = dsize;
231 6f4d00ee 2013-09-23 0intro assert(psize && dsize);
232 6f4d00ee 2013-09-23 0intro e.flags = VtEntryActive;
233 6f4d00ee 2013-09-23 0intro if(dir)
234 4b576658 2013-09-23 0intro e.flags |= _VtEntryDir;
235 6f4d00ee 2013-09-23 0intro e.depth = 0;
236 6f4d00ee 2013-09-23 0intro e.size = 0;
237 4b576658 2013-09-23 0intro memmove(e.score, vtzeroscore, VtScoreSize);
238 6f4d00ee 2013-09-23 0intro e.tag = 0;
239 6f4d00ee 2013-09-23 0intro e.snap = 0;
240 6f4d00ee 2013-09-23 0intro e.archive = 0;
241 6f4d00ee 2013-09-23 0intro entryPack(&e, b->data, i);
242 6f4d00ee 2013-09-23 0intro blockDirty(b);
243 6f4d00ee 2013-09-23 0intro
244 6f4d00ee 2013-09-23 0intro offset = bn*epb + i;
245 6f4d00ee 2013-09-23 0intro if(offset+1 > size){
246 6f4d00ee 2013-09-23 0intro if(!sourceSetDirSize(r, offset+1)){
247 6f4d00ee 2013-09-23 0intro blockPut(b);
248 6f4d00ee 2013-09-23 0intro return nil;
249 6f4d00ee 2013-09-23 0intro }
250 6f4d00ee 2013-09-23 0intro }
251 6f4d00ee 2013-09-23 0intro
252 6f4d00ee 2013-09-23 0intro rr = sourceAlloc(r->fs, b, r, offset, OReadWrite, 0);
253 6f4d00ee 2013-09-23 0intro blockPut(b);
254 6f4d00ee 2013-09-23 0intro return rr;
255 6f4d00ee 2013-09-23 0intro }
256 6f4d00ee 2013-09-23 0intro
257 6f4d00ee 2013-09-23 0intro static int
258 6f4d00ee 2013-09-23 0intro sourceKill(Source *r, int doremove)
259 6f4d00ee 2013-09-23 0intro {
260 6f4d00ee 2013-09-23 0intro Entry e;
261 6f4d00ee 2013-09-23 0intro Block *b;
262 6f4d00ee 2013-09-23 0intro u32int addr;
263 6f4d00ee 2013-09-23 0intro u32int tag;
264 6f4d00ee 2013-09-23 0intro int type;
265 6f4d00ee 2013-09-23 0intro
266 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
267 6f4d00ee 2013-09-23 0intro b = sourceLoad(r, &e);
268 6f4d00ee 2013-09-23 0intro if(b == nil)
269 6f4d00ee 2013-09-23 0intro return 0;
270 6f4d00ee 2013-09-23 0intro
271 6f4d00ee 2013-09-23 0intro assert(b->l.epoch == r->fs->ehi);
272 6f4d00ee 2013-09-23 0intro
273 6f4d00ee 2013-09-23 0intro if(doremove==0 && e.size == 0){
274 6f4d00ee 2013-09-23 0intro /* already truncated */
275 6f4d00ee 2013-09-23 0intro blockPut(b);
276 6f4d00ee 2013-09-23 0intro return 1;
277 6f4d00ee 2013-09-23 0intro }
278 6f4d00ee 2013-09-23 0intro
279 6f4d00ee 2013-09-23 0intro /* remember info on link we are removing */
280 6f4d00ee 2013-09-23 0intro addr = globalToLocal(e.score);
281 6f4d00ee 2013-09-23 0intro type = entryType(&e);
282 6f4d00ee 2013-09-23 0intro tag = e.tag;
283 6f4d00ee 2013-09-23 0intro
284 6f4d00ee 2013-09-23 0intro if(doremove){
285 6f4d00ee 2013-09-23 0intro if(e.gen != ~0)
286 6f4d00ee 2013-09-23 0intro e.gen++;
287 6f4d00ee 2013-09-23 0intro e.dsize = 0;
288 6f4d00ee 2013-09-23 0intro e.psize = 0;
289 6f4d00ee 2013-09-23 0intro e.flags = 0;
290 6f4d00ee 2013-09-23 0intro }else{
291 6f4d00ee 2013-09-23 0intro e.flags &= ~VtEntryLocal;
292 6f4d00ee 2013-09-23 0intro }
293 6f4d00ee 2013-09-23 0intro e.depth = 0;
294 6f4d00ee 2013-09-23 0intro e.size = 0;
295 6f4d00ee 2013-09-23 0intro e.tag = 0;
296 4b576658 2013-09-23 0intro memmove(e.score, vtzeroscore, VtScoreSize);
297 6f4d00ee 2013-09-23 0intro entryPack(&e, b->data, r->offset % r->epb);
298 6f4d00ee 2013-09-23 0intro blockDirty(b);
299 6f4d00ee 2013-09-23 0intro if(addr != NilBlock)
300 6f4d00ee 2013-09-23 0intro blockRemoveLink(b, addr, type, tag, 1);
301 6f4d00ee 2013-09-23 0intro blockPut(b);
302 6f4d00ee 2013-09-23 0intro
303 6f4d00ee 2013-09-23 0intro if(doremove){
304 6f4d00ee 2013-09-23 0intro sourceUnlock(r);
305 6f4d00ee 2013-09-23 0intro sourceClose(r);
306 6f4d00ee 2013-09-23 0intro }
307 6f4d00ee 2013-09-23 0intro
308 6f4d00ee 2013-09-23 0intro return 1;
309 6f4d00ee 2013-09-23 0intro }
310 6f4d00ee 2013-09-23 0intro
311 6f4d00ee 2013-09-23 0intro int
312 6f4d00ee 2013-09-23 0intro sourceRemove(Source *r)
313 6f4d00ee 2013-09-23 0intro {
314 6f4d00ee 2013-09-23 0intro return sourceKill(r, 1);
315 6f4d00ee 2013-09-23 0intro }
316 6f4d00ee 2013-09-23 0intro
317 6f4d00ee 2013-09-23 0intro int
318 6f4d00ee 2013-09-23 0intro sourceTruncate(Source *r)
319 6f4d00ee 2013-09-23 0intro {
320 6f4d00ee 2013-09-23 0intro return sourceKill(r, 0);
321 6f4d00ee 2013-09-23 0intro }
322 6f4d00ee 2013-09-23 0intro
323 6f4d00ee 2013-09-23 0intro uvlong
324 6f4d00ee 2013-09-23 0intro sourceGetSize(Source *r)
325 6f4d00ee 2013-09-23 0intro {
326 6f4d00ee 2013-09-23 0intro Entry e;
327 6f4d00ee 2013-09-23 0intro Block *b;
328 6f4d00ee 2013-09-23 0intro
329 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
330 6f4d00ee 2013-09-23 0intro b = sourceLoad(r, &e);
331 6f4d00ee 2013-09-23 0intro if(b == nil)
332 6f4d00ee 2013-09-23 0intro return 0;
333 6f4d00ee 2013-09-23 0intro blockPut(b);
334 6f4d00ee 2013-09-23 0intro
335 6f4d00ee 2013-09-23 0intro return e.size;
336 6f4d00ee 2013-09-23 0intro }
337 6f4d00ee 2013-09-23 0intro
338 6f4d00ee 2013-09-23 0intro static int
339 6f4d00ee 2013-09-23 0intro sourceShrinkSize(Source *r, Entry *e, uvlong size)
340 6f4d00ee 2013-09-23 0intro {
341 6f4d00ee 2013-09-23 0intro int i, type, ppb;
342 6f4d00ee 2013-09-23 0intro uvlong ptrsz;
343 6f4d00ee 2013-09-23 0intro u32int addr;
344 6f4d00ee 2013-09-23 0intro uchar score[VtScoreSize];
345 6f4d00ee 2013-09-23 0intro Block *b;
346 6f4d00ee 2013-09-23 0intro
347 6f4d00ee 2013-09-23 0intro type = entryType(e);
348 6f4d00ee 2013-09-23 0intro b = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite);
349 6f4d00ee 2013-09-23 0intro if(b == nil)
350 6f4d00ee 2013-09-23 0intro return 0;
351 6f4d00ee 2013-09-23 0intro
352 6f4d00ee 2013-09-23 0intro ptrsz = e->dsize;
353 6f4d00ee 2013-09-23 0intro ppb = e->psize/VtScoreSize;
354 6f4d00ee 2013-09-23 0intro for(i=0; i+1<e->depth; i++)
355 6f4d00ee 2013-09-23 0intro ptrsz *= ppb;
356 6f4d00ee 2013-09-23 0intro
357 6f4d00ee 2013-09-23 0intro while(type&BtLevelMask){
358 6f4d00ee 2013-09-23 0intro if(b->addr == NilBlock || b->l.epoch != r->fs->ehi){
359 6f4d00ee 2013-09-23 0intro /* not worth copying the block just so we can zero some of it */
360 6f4d00ee 2013-09-23 0intro blockPut(b);
361 6f4d00ee 2013-09-23 0intro return 0;
362 6f4d00ee 2013-09-23 0intro }
363 6f4d00ee 2013-09-23 0intro
364 6f4d00ee 2013-09-23 0intro /*
365 6f4d00ee 2013-09-23 0intro * invariant: each pointer in the tree rooted at b accounts for ptrsz bytes
366 6f4d00ee 2013-09-23 0intro */
367 6f4d00ee 2013-09-23 0intro
368 6f4d00ee 2013-09-23 0intro /* zero the pointers to unnecessary blocks */
369 6f4d00ee 2013-09-23 0intro i = (size+ptrsz-1)/ptrsz;
370 6f4d00ee 2013-09-23 0intro for(; i<ppb; i++){
371 6f4d00ee 2013-09-23 0intro addr = globalToLocal(b->data+i*VtScoreSize);
372 4b576658 2013-09-23 0intro memmove(b->data+i*VtScoreSize, vtzeroscore, VtScoreSize);
373 6f4d00ee 2013-09-23 0intro blockDirty(b);
374 6f4d00ee 2013-09-23 0intro if(addr != NilBlock)
375 6f4d00ee 2013-09-23 0intro blockRemoveLink(b, addr, type-1, e->tag, 1);
376 6f4d00ee 2013-09-23 0intro }
377 6f4d00ee 2013-09-23 0intro
378 6f4d00ee 2013-09-23 0intro /* recurse (go around again) on the partially necessary block */
379 6f4d00ee 2013-09-23 0intro i = size/ptrsz;
380 6f4d00ee 2013-09-23 0intro size = size%ptrsz;
381 6f4d00ee 2013-09-23 0intro if(size == 0){
382 6f4d00ee 2013-09-23 0intro blockPut(b);
383 6f4d00ee 2013-09-23 0intro return 1;
384 6f4d00ee 2013-09-23 0intro }
385 6f4d00ee 2013-09-23 0intro ptrsz /= ppb;
386 6f4d00ee 2013-09-23 0intro type--;
387 6f4d00ee 2013-09-23 0intro memmove(score, b->data+i*VtScoreSize, VtScoreSize);
388 6f4d00ee 2013-09-23 0intro blockPut(b);
389 6f4d00ee 2013-09-23 0intro b = cacheGlobal(r->fs->cache, score, type, e->tag, OReadWrite);
390 6f4d00ee 2013-09-23 0intro if(b == nil)
391 6f4d00ee 2013-09-23 0intro return 0;
392 6f4d00ee 2013-09-23 0intro }
393 6f4d00ee 2013-09-23 0intro
394 6f4d00ee 2013-09-23 0intro if(b->addr == NilBlock || b->l.epoch != r->fs->ehi){
395 6f4d00ee 2013-09-23 0intro blockPut(b);
396 6f4d00ee 2013-09-23 0intro return 0;
397 6f4d00ee 2013-09-23 0intro }
398 6f4d00ee 2013-09-23 0intro
399 6f4d00ee 2013-09-23 0intro /*
400 6f4d00ee 2013-09-23 0intro * No one ever truncates BtDir blocks.
401 6f4d00ee 2013-09-23 0intro */
402 6f4d00ee 2013-09-23 0intro if(type == BtData && e->dsize > size){
403 6f4d00ee 2013-09-23 0intro memset(b->data+size, 0, e->dsize-size);
404 6f4d00ee 2013-09-23 0intro blockDirty(b);
405 6f4d00ee 2013-09-23 0intro }
406 6f4d00ee 2013-09-23 0intro blockPut(b);
407 6f4d00ee 2013-09-23 0intro return 1;
408 6f4d00ee 2013-09-23 0intro }
409 6f4d00ee 2013-09-23 0intro
410 6f4d00ee 2013-09-23 0intro int
411 6f4d00ee 2013-09-23 0intro sourceSetSize(Source *r, uvlong size)
412 6f4d00ee 2013-09-23 0intro {
413 6f4d00ee 2013-09-23 0intro int depth;
414 6f4d00ee 2013-09-23 0intro Entry e;
415 6f4d00ee 2013-09-23 0intro Block *b;
416 6f4d00ee 2013-09-23 0intro
417 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
418 6f4d00ee 2013-09-23 0intro if(size == 0)
419 6f4d00ee 2013-09-23 0intro return sourceTruncate(r);
420 6f4d00ee 2013-09-23 0intro
421 6f4d00ee 2013-09-23 0intro if(size > VtMaxFileSize || size > ((uvlong)MaxBlock)*r->dsize){
422 4b576658 2013-09-23 0intro werrstr(ETooBig);
423 6f4d00ee 2013-09-23 0intro return 0;
424 6f4d00ee 2013-09-23 0intro }
425 6f4d00ee 2013-09-23 0intro
426 6f4d00ee 2013-09-23 0intro b = sourceLoad(r, &e);
427 6f4d00ee 2013-09-23 0intro if(b == nil)
428 6f4d00ee 2013-09-23 0intro return 0;
429 6f4d00ee 2013-09-23 0intro
430 6f4d00ee 2013-09-23 0intro /* quick out */
431 6f4d00ee 2013-09-23 0intro if(e.size == size){
432 6f4d00ee 2013-09-23 0intro blockPut(b);
433 6f4d00ee 2013-09-23 0intro return 1;
434 6f4d00ee 2013-09-23 0intro }
435 6f4d00ee 2013-09-23 0intro
436 6f4d00ee 2013-09-23 0intro depth = sizeToDepth(size, e.psize, e.dsize);
437 6f4d00ee 2013-09-23 0intro
438 6f4d00ee 2013-09-23 0intro if(depth < e.depth){
439 6f4d00ee 2013-09-23 0intro if(!sourceShrinkDepth(r, b, &e, depth)){
440 6f4d00ee 2013-09-23 0intro blockPut(b);
441 6f4d00ee 2013-09-23 0intro return 0;
442 6f4d00ee 2013-09-23 0intro }
443 6f4d00ee 2013-09-23 0intro }else if(depth > e.depth){
444 6f4d00ee 2013-09-23 0intro if(!sourceGrowDepth(r, b, &e, depth)){
445 6f4d00ee 2013-09-23 0intro blockPut(b);
446 6f4d00ee 2013-09-23 0intro return 0;
447 6f4d00ee 2013-09-23 0intro }
448 6f4d00ee 2013-09-23 0intro }
449 6f4d00ee 2013-09-23 0intro
450 6f4d00ee 2013-09-23 0intro if(size < e.size)
451 6f4d00ee 2013-09-23 0intro sourceShrinkSize(r, &e, size);
452 6f4d00ee 2013-09-23 0intro
453 6f4d00ee 2013-09-23 0intro e.size = size;
454 6f4d00ee 2013-09-23 0intro entryPack(&e, b->data, r->offset % r->epb);
455 6f4d00ee 2013-09-23 0intro blockDirty(b);
456 6f4d00ee 2013-09-23 0intro blockPut(b);
457 6f4d00ee 2013-09-23 0intro
458 6f4d00ee 2013-09-23 0intro return 1;
459 6f4d00ee 2013-09-23 0intro }
460 6f4d00ee 2013-09-23 0intro
461 6f4d00ee 2013-09-23 0intro int
462 6f4d00ee 2013-09-23 0intro sourceSetDirSize(Source *r, ulong ds)
463 6f4d00ee 2013-09-23 0intro {
464 6f4d00ee 2013-09-23 0intro uvlong size;
465 6f4d00ee 2013-09-23 0intro int epb;
466 6f4d00ee 2013-09-23 0intro
467 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
468 6f4d00ee 2013-09-23 0intro epb = r->dsize/VtEntrySize;
469 6f4d00ee 2013-09-23 0intro
470 6f4d00ee 2013-09-23 0intro size = (uvlong)r->dsize*(ds/epb);
471 6f4d00ee 2013-09-23 0intro size += VtEntrySize*(ds%epb);
472 6f4d00ee 2013-09-23 0intro return sourceSetSize(r, size);
473 6f4d00ee 2013-09-23 0intro }
474 6f4d00ee 2013-09-23 0intro
475 6f4d00ee 2013-09-23 0intro ulong
476 6f4d00ee 2013-09-23 0intro sourceGetDirSize(Source *r)
477 6f4d00ee 2013-09-23 0intro {
478 6f4d00ee 2013-09-23 0intro ulong ds;
479 6f4d00ee 2013-09-23 0intro uvlong size;
480 6f4d00ee 2013-09-23 0intro int epb;
481 6f4d00ee 2013-09-23 0intro
482 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
483 6f4d00ee 2013-09-23 0intro epb = r->dsize/VtEntrySize;
484 6f4d00ee 2013-09-23 0intro
485 6f4d00ee 2013-09-23 0intro size = sourceGetSize(r);
486 6f4d00ee 2013-09-23 0intro ds = epb*(size/r->dsize);
487 6f4d00ee 2013-09-23 0intro ds += (size%r->dsize)/VtEntrySize;
488 6f4d00ee 2013-09-23 0intro return ds;
489 6f4d00ee 2013-09-23 0intro }
490 6f4d00ee 2013-09-23 0intro
491 6f4d00ee 2013-09-23 0intro int
492 6f4d00ee 2013-09-23 0intro sourceGetEntry(Source *r, Entry *e)
493 6f4d00ee 2013-09-23 0intro {
494 6f4d00ee 2013-09-23 0intro Block *b;
495 6f4d00ee 2013-09-23 0intro
496 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
497 6f4d00ee 2013-09-23 0intro b = sourceLoad(r, e);
498 6f4d00ee 2013-09-23 0intro if(b == nil)
499 6f4d00ee 2013-09-23 0intro return 0;
500 6f4d00ee 2013-09-23 0intro blockPut(b);
501 6f4d00ee 2013-09-23 0intro
502 6f4d00ee 2013-09-23 0intro return 1;
503 6f4d00ee 2013-09-23 0intro }
504 6f4d00ee 2013-09-23 0intro
505 6f4d00ee 2013-09-23 0intro /*
506 6f4d00ee 2013-09-23 0intro * Must be careful with this. Doesn't record
507 6f4d00ee 2013-09-23 0intro * dependencies, so don't introduce any!
508 6f4d00ee 2013-09-23 0intro */
509 6f4d00ee 2013-09-23 0intro int
510 6f4d00ee 2013-09-23 0intro sourceSetEntry(Source *r, Entry *e)
511 6f4d00ee 2013-09-23 0intro {
512 6f4d00ee 2013-09-23 0intro Block *b;
513 6f4d00ee 2013-09-23 0intro Entry oe;
514 6f4d00ee 2013-09-23 0intro
515 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
516 6f4d00ee 2013-09-23 0intro b = sourceLoad(r, &oe);
517 6f4d00ee 2013-09-23 0intro if(b == nil)
518 6f4d00ee 2013-09-23 0intro return 0;
519 6f4d00ee 2013-09-23 0intro entryPack(e, b->data, r->offset%r->epb);
520 6f4d00ee 2013-09-23 0intro blockDirty(b);
521 6f4d00ee 2013-09-23 0intro blockPut(b);
522 6f4d00ee 2013-09-23 0intro
523 6f4d00ee 2013-09-23 0intro return 1;
524 6f4d00ee 2013-09-23 0intro }
525 6f4d00ee 2013-09-23 0intro
526 6f4d00ee 2013-09-23 0intro static Block *
527 6f4d00ee 2013-09-23 0intro blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e)
528 6f4d00ee 2013-09-23 0intro {
529 6f4d00ee 2013-09-23 0intro Block *b;
530 6f4d00ee 2013-09-23 0intro Cache *c;
531 6f4d00ee 2013-09-23 0intro u32int addr;
532 6f4d00ee 2013-09-23 0intro int type;
533 6f4d00ee 2013-09-23 0intro uchar oscore[VtScoreSize], score[VtScoreSize];
534 6f4d00ee 2013-09-23 0intro Entry oe;
535 6f4d00ee 2013-09-23 0intro
536 6f4d00ee 2013-09-23 0intro c = fs->cache;
537 6f4d00ee 2013-09-23 0intro
538 6f4d00ee 2013-09-23 0intro if((p->l.type & BtLevelMask) == 0){
539 6f4d00ee 2013-09-23 0intro assert(p->l.type == BtDir);
540 6f4d00ee 2013-09-23 0intro type = entryType(e);
541 6f4d00ee 2013-09-23 0intro b = cacheGlobal(c, e->score, type, e->tag, mode);
542 6f4d00ee 2013-09-23 0intro }else{
543 6f4d00ee 2013-09-23 0intro type = p->l.type - 1;
544 6f4d00ee 2013-09-23 0intro b = cacheGlobal(c, p->data + index*VtScoreSize, type, e->tag, mode);
545 6f4d00ee 2013-09-23 0intro }
546 6f4d00ee 2013-09-23 0intro
547 6f4d00ee 2013-09-23 0intro if(b)
548 6f4d00ee 2013-09-23 0intro b->pc = getcallerpc(&p);
549 6f4d00ee 2013-09-23 0intro
550 6f4d00ee 2013-09-23 0intro if(b == nil || mode == OReadOnly)
551 6f4d00ee 2013-09-23 0intro return b;
552 6f4d00ee 2013-09-23 0intro
553 6f4d00ee 2013-09-23 0intro if(p->l.epoch != fs->ehi){
554 6f4d00ee 2013-09-23 0intro fprint(2, "blockWalk: parent not writable\n");
555 6f4d00ee 2013-09-23 0intro abort();
556 6f4d00ee 2013-09-23 0intro }
557 6f4d00ee 2013-09-23 0intro if(b->l.epoch == fs->ehi)
558 6f4d00ee 2013-09-23 0intro return b;
559 6f4d00ee 2013-09-23 0intro
560 6f4d00ee 2013-09-23 0intro oe = *e;
561 6f4d00ee 2013-09-23 0intro
562 6f4d00ee 2013-09-23 0intro /*
563 6f4d00ee 2013-09-23 0intro * Copy on write.
564 6f4d00ee 2013-09-23 0intro */
565 6f4d00ee 2013-09-23 0intro if(e->tag == 0){
566 6f4d00ee 2013-09-23 0intro assert(p->l.type == BtDir);
567 6f4d00ee 2013-09-23 0intro e->tag = tagGen();
568 6f4d00ee 2013-09-23 0intro e->flags |= VtEntryLocal;
569 6f4d00ee 2013-09-23 0intro }
570 6f4d00ee 2013-09-23 0intro
571 6f4d00ee 2013-09-23 0intro addr = b->addr;
572 6f4d00ee 2013-09-23 0intro b = blockCopy(b, e->tag, fs->ehi, fs->elo);
573 6f4d00ee 2013-09-23 0intro if(b == nil)
574 6f4d00ee 2013-09-23 0intro return nil;
575 6f4d00ee 2013-09-23 0intro
576 6f4d00ee 2013-09-23 0intro b->pc = getcallerpc(&p);
577 6f4d00ee 2013-09-23 0intro assert(b->l.epoch == fs->ehi);
578 6f4d00ee 2013-09-23 0intro
579 6f4d00ee 2013-09-23 0intro blockDirty(b);
580 6f4d00ee 2013-09-23 0intro memmove(score, b->score, VtScoreSize);
581 6f4d00ee 2013-09-23 0intro if(p->l.type == BtDir){
582 6f4d00ee 2013-09-23 0intro memmove(e->score, b->score, VtScoreSize);
583 6f4d00ee 2013-09-23 0intro entryPack(e, p->data, index);
584 6f4d00ee 2013-09-23 0intro blockDependency(p, b, index, nil, &oe);
585 6f4d00ee 2013-09-23 0intro }else{
586 6f4d00ee 2013-09-23 0intro memmove(oscore, p->data+index*VtScoreSize, VtScoreSize);
587 6f4d00ee 2013-09-23 0intro memmove(p->data+index*VtScoreSize, b->score, VtScoreSize);
588 6f4d00ee 2013-09-23 0intro blockDependency(p, b, index, oscore, nil);
589 6f4d00ee 2013-09-23 0intro }
590 6f4d00ee 2013-09-23 0intro blockDirty(p);
591 6f4d00ee 2013-09-23 0intro
592 6f4d00ee 2013-09-23 0intro if(addr != NilBlock)
593 6f4d00ee 2013-09-23 0intro blockRemoveLink(p, addr, type, e->tag, 0);
594 6f4d00ee 2013-09-23 0intro
595 6f4d00ee 2013-09-23 0intro return b;
596 6f4d00ee 2013-09-23 0intro }
597 6f4d00ee 2013-09-23 0intro
598 6f4d00ee 2013-09-23 0intro /*
599 6f4d00ee 2013-09-23 0intro * Change the depth of the source r.
600 6f4d00ee 2013-09-23 0intro * The entry e for r is contained in block p.
601 6f4d00ee 2013-09-23 0intro */
602 6f4d00ee 2013-09-23 0intro static int
603 6f4d00ee 2013-09-23 0intro sourceGrowDepth(Source *r, Block *p, Entry *e, int depth)
604 6f4d00ee 2013-09-23 0intro {
605 6f4d00ee 2013-09-23 0intro Block *b, *bb;
606 6f4d00ee 2013-09-23 0intro u32int tag;
607 6f4d00ee 2013-09-23 0intro int type;
608 6f4d00ee 2013-09-23 0intro Entry oe;
609 6f4d00ee 2013-09-23 0intro
610 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
611 6f4d00ee 2013-09-23 0intro assert(depth <= VtPointerDepth);
612 6f4d00ee 2013-09-23 0intro
613 6f4d00ee 2013-09-23 0intro type = entryType(e);
614 6f4d00ee 2013-09-23 0intro b = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite);
615 6f4d00ee 2013-09-23 0intro if(b == nil)
616 6f4d00ee 2013-09-23 0intro return 0;
617 6f4d00ee 2013-09-23 0intro
618 6f4d00ee 2013-09-23 0intro tag = e->tag;
619 6f4d00ee 2013-09-23 0intro if(tag == 0)
620 6f4d00ee 2013-09-23 0intro tag = tagGen();
621 6f4d00ee 2013-09-23 0intro
622 6f4d00ee 2013-09-23 0intro oe = *e;
623 6f4d00ee 2013-09-23 0intro
624 6f4d00ee 2013-09-23 0intro /*
625 6f4d00ee 2013-09-23 0intro * Keep adding layers until we get to the right depth
626 6f4d00ee 2013-09-23 0intro * or an error occurs.
627 6f4d00ee 2013-09-23 0intro */
628 6f4d00ee 2013-09-23 0intro while(e->depth < depth){
629 6f4d00ee 2013-09-23 0intro bb = cacheAllocBlock(r->fs->cache, type+1, tag, r->fs->ehi, r->fs->elo);
630 6f4d00ee 2013-09-23 0intro if(bb == nil)
631 6f4d00ee 2013-09-23 0intro break;
632 6f4d00ee 2013-09-23 0intro //fprint(2, "alloc %lux grow %V\n", bb->addr, b->score);
633 6f4d00ee 2013-09-23 0intro memmove(bb->data, b->score, VtScoreSize);
634 6f4d00ee 2013-09-23 0intro memmove(e->score, bb->score, VtScoreSize);
635 6f4d00ee 2013-09-23 0intro e->depth++;
636 6f4d00ee 2013-09-23 0intro type++;
637 6f4d00ee 2013-09-23 0intro e->tag = tag;
638 6f4d00ee 2013-09-23 0intro e->flags |= VtEntryLocal;
639 4b576658 2013-09-23 0intro blockDependency(bb, b, 0, vtzeroscore, nil);
640 6f4d00ee 2013-09-23 0intro blockPut(b);
641 6f4d00ee 2013-09-23 0intro b = bb;
642 6f4d00ee 2013-09-23 0intro blockDirty(b);
643 6f4d00ee 2013-09-23 0intro }
644 6f4d00ee 2013-09-23 0intro
645 6f4d00ee 2013-09-23 0intro entryPack(e, p->data, r->offset % r->epb);
646 6f4d00ee 2013-09-23 0intro blockDependency(p, b, r->offset % r->epb, nil, &oe);
647 6f4d00ee 2013-09-23 0intro blockPut(b);
648 6f4d00ee 2013-09-23 0intro blockDirty(p);
649 6f4d00ee 2013-09-23 0intro
650 6f4d00ee 2013-09-23 0intro return e->depth == depth;
651 6f4d00ee 2013-09-23 0intro }
652 6f4d00ee 2013-09-23 0intro
653 6f4d00ee 2013-09-23 0intro static int
654 6f4d00ee 2013-09-23 0intro sourceShrinkDepth(Source *r, Block *p, Entry *e, int depth)
655 6f4d00ee 2013-09-23 0intro {
656 6f4d00ee 2013-09-23 0intro Block *b, *nb, *ob, *rb;
657 6f4d00ee 2013-09-23 0intro u32int tag;
658 6f4d00ee 2013-09-23 0intro int type, d;
659 6f4d00ee 2013-09-23 0intro Entry oe;
660 6f4d00ee 2013-09-23 0intro
661 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
662 6f4d00ee 2013-09-23 0intro assert(depth <= VtPointerDepth);
663 6f4d00ee 2013-09-23 0intro
664 6f4d00ee 2013-09-23 0intro type = entryType(e);
665 6f4d00ee 2013-09-23 0intro rb = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite);
666 6f4d00ee 2013-09-23 0intro if(rb == nil)
667 6f4d00ee 2013-09-23 0intro return 0;
668 6f4d00ee 2013-09-23 0intro
669 6f4d00ee 2013-09-23 0intro tag = e->tag;
670 6f4d00ee 2013-09-23 0intro if(tag == 0)
671 6f4d00ee 2013-09-23 0intro tag = tagGen();
672 6f4d00ee 2013-09-23 0intro
673 6f4d00ee 2013-09-23 0intro /*
674 6f4d00ee 2013-09-23 0intro * Walk down to the new root block.
675 6f4d00ee 2013-09-23 0intro * We may stop early, but something is better than nothing.
676 6f4d00ee 2013-09-23 0intro */
677 6f4d00ee 2013-09-23 0intro oe = *e;
678 6f4d00ee 2013-09-23 0intro
679 6f4d00ee 2013-09-23 0intro ob = nil;
680 6f4d00ee 2013-09-23 0intro b = rb;
681 6f4d00ee 2013-09-23 0intro /* BUG: explain type++. i think it is a real bug */
682 6f4d00ee 2013-09-23 0intro for(d=e->depth; d > depth; d--, type++){
683 6f4d00ee 2013-09-23 0intro nb = cacheGlobal(r->fs->cache, b->data, type-1, tag, OReadWrite);
684 6f4d00ee 2013-09-23 0intro if(nb == nil)
685 6f4d00ee 2013-09-23 0intro break;
686 6f4d00ee 2013-09-23 0intro if(ob!=nil && ob!=rb)
687 6f4d00ee 2013-09-23 0intro blockPut(ob);
688 6f4d00ee 2013-09-23 0intro ob = b;
689 6f4d00ee 2013-09-23 0intro b = nb;
690 6f4d00ee 2013-09-23 0intro }
691 6f4d00ee 2013-09-23 0intro
692 6f4d00ee 2013-09-23 0intro if(b == rb){
693 6f4d00ee 2013-09-23 0intro blockPut(rb);
694 6f4d00ee 2013-09-23 0intro return 0;
695 6f4d00ee 2013-09-23 0intro }
696 6f4d00ee 2013-09-23 0intro
697 6f4d00ee 2013-09-23 0intro /*
698 6f4d00ee 2013-09-23 0intro * Right now, e points at the root block rb, b is the new root block,
699 6f4d00ee 2013-09-23 0intro * and ob points at b. To update:
700 6f4d00ee 2013-09-23 0intro *
701 6f4d00ee 2013-09-23 0intro * (i) change e to point at b
702 6f4d00ee 2013-09-23 0intro * (ii) zero the pointer ob -> b
703 6f4d00ee 2013-09-23 0intro * (iii) free the root block
704 6f4d00ee 2013-09-23 0intro *
705 6f4d00ee 2013-09-23 0intro * p (the block containing e) must be written before
706 6f4d00ee 2013-09-23 0intro * anything else.
707 6f4d00ee 2013-09-23 0intro */
708 6f4d00ee 2013-09-23 0intro
709 6f4d00ee 2013-09-23 0intro /* (i) */
710 6f4d00ee 2013-09-23 0intro e->depth = d;
711 6f4d00ee 2013-09-23 0intro /* might have been local and now global; reverse cannot happen */
712 6f4d00ee 2013-09-23 0intro if(globalToLocal(b->score) == NilBlock)
713 6f4d00ee 2013-09-23 0intro e->flags &= ~VtEntryLocal;
714 6f4d00ee 2013-09-23 0intro memmove(e->score, b->score, VtScoreSize);
715 6f4d00ee 2013-09-23 0intro entryPack(e, p->data, r->offset % r->epb);
716 6f4d00ee 2013-09-23 0intro blockDependency(p, b, r->offset % r->epb, nil, &oe);
717 6f4d00ee 2013-09-23 0intro blockDirty(p);
718 6f4d00ee 2013-09-23 0intro
719 6f4d00ee 2013-09-23 0intro /* (ii) */
720 4b576658 2013-09-23 0intro memmove(ob->data, vtzeroscore, VtScoreSize);
721 6f4d00ee 2013-09-23 0intro blockDependency(ob, p, 0, b->score, nil);
722 6f4d00ee 2013-09-23 0intro blockDirty(ob);
723 6f4d00ee 2013-09-23 0intro
724 6f4d00ee 2013-09-23 0intro /* (iii) */
725 6f4d00ee 2013-09-23 0intro if(rb->addr != NilBlock)
726 6f4d00ee 2013-09-23 0intro blockRemoveLink(p, rb->addr, rb->l.type, rb->l.tag, 1);
727 6f4d00ee 2013-09-23 0intro
728 6f4d00ee 2013-09-23 0intro blockPut(rb);
729 6f4d00ee 2013-09-23 0intro if(ob!=nil && ob!=rb)
730 6f4d00ee 2013-09-23 0intro blockPut(ob);
731 6f4d00ee 2013-09-23 0intro blockPut(b);
732 6f4d00ee 2013-09-23 0intro
733 6f4d00ee 2013-09-23 0intro return d == depth;
734 6f4d00ee 2013-09-23 0intro }
735 6f4d00ee 2013-09-23 0intro
736 6f4d00ee 2013-09-23 0intro /*
737 6f4d00ee 2013-09-23 0intro * Normally we return the block at the given number.
738 6f4d00ee 2013-09-23 0intro * If early is set, we stop earlier in the tree. Setting early
739 6f4d00ee 2013-09-23 0intro * to 1 gives us the block that contains the pointer to bn.
740 6f4d00ee 2013-09-23 0intro */
741 6f4d00ee 2013-09-23 0intro Block *
742 6f4d00ee 2013-09-23 0intro _sourceBlock(Source *r, ulong bn, int mode, int early, ulong tag)
743 6f4d00ee 2013-09-23 0intro {
744 6f4d00ee 2013-09-23 0intro Block *b, *bb;
745 6f4d00ee 2013-09-23 0intro int index[VtPointerDepth+1];
746 6f4d00ee 2013-09-23 0intro Entry e;
747 6f4d00ee 2013-09-23 0intro int i, np;
748 6f4d00ee 2013-09-23 0intro int m;
749 6f4d00ee 2013-09-23 0intro
750 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
751 6f4d00ee 2013-09-23 0intro assert(bn != NilBlock);
752 6f4d00ee 2013-09-23 0intro
753 6f4d00ee 2013-09-23 0intro /* mode for intermediate block */
754 6f4d00ee 2013-09-23 0intro m = mode;
755 6f4d00ee 2013-09-23 0intro if(m == OOverWrite)
756 6f4d00ee 2013-09-23 0intro m = OReadWrite;
757 6f4d00ee 2013-09-23 0intro
758 6f4d00ee 2013-09-23 0intro b = sourceLoad(r, &e);
759 6f4d00ee 2013-09-23 0intro if(b == nil)
760 6f4d00ee 2013-09-23 0intro return nil;
761 6f4d00ee 2013-09-23 0intro if(r->issnapshot && (e.flags & VtEntryNoArchive)){
762 6f4d00ee 2013-09-23 0intro blockPut(b);
763 4b576658 2013-09-23 0intro werrstr(ENotArchived);
764 6f4d00ee 2013-09-23 0intro return nil;
765 6f4d00ee 2013-09-23 0intro }
766 6f4d00ee 2013-09-23 0intro
767 6f4d00ee 2013-09-23 0intro if(tag){
768 6f4d00ee 2013-09-23 0intro if(e.tag == 0)
769 6f4d00ee 2013-09-23 0intro e.tag = tag;
770 6f4d00ee 2013-09-23 0intro else if(e.tag != tag){
771 6f4d00ee 2013-09-23 0intro fprint(2, "tag mismatch\n");
772 4b576658 2013-09-23 0intro werrstr("tag mismatch");
773 6f4d00ee 2013-09-23 0intro goto Err;
774 6f4d00ee 2013-09-23 0intro }
775 6f4d00ee 2013-09-23 0intro }
776 6f4d00ee 2013-09-23 0intro
777 6f4d00ee 2013-09-23 0intro np = e.psize/VtScoreSize;
778 6f4d00ee 2013-09-23 0intro memset(index, 0, sizeof(index));
779 6f4d00ee 2013-09-23 0intro for(i=0; bn > 0; i++){
780 6f4d00ee 2013-09-23 0intro if(i >= VtPointerDepth){
781 4b576658 2013-09-23 0intro werrstr(EBadAddr);
782 6f4d00ee 2013-09-23 0intro goto Err;
783 6f4d00ee 2013-09-23 0intro }
784 6f4d00ee 2013-09-23 0intro index[i] = bn % np;
785 6f4d00ee 2013-09-23 0intro bn /= np;
786 6f4d00ee 2013-09-23 0intro }
787 6f4d00ee 2013-09-23 0intro
788 6f4d00ee 2013-09-23 0intro if(i > e.depth){
789 6f4d00ee 2013-09-23 0intro if(mode == OReadOnly){
790 4b576658 2013-09-23 0intro werrstr(EBadAddr);
791 6f4d00ee 2013-09-23 0intro goto Err;
792 6f4d00ee 2013-09-23 0intro }
793 6f4d00ee 2013-09-23 0intro if(!sourceGrowDepth(r, b, &e, i))
794 6f4d00ee 2013-09-23 0intro goto Err;
795 6f4d00ee 2013-09-23 0intro }
796 6f4d00ee 2013-09-23 0intro
797 6f4d00ee 2013-09-23 0intro index[e.depth] = r->offset % r->epb;
798 6f4d00ee 2013-09-23 0intro
799 6f4d00ee 2013-09-23 0intro for(i=e.depth; i>=early; i--){
800 6f4d00ee 2013-09-23 0intro bb = blockWalk(b, index[i], m, r->fs, &e);
801 6f4d00ee 2013-09-23 0intro if(bb == nil)
802 6f4d00ee 2013-09-23 0intro goto Err;
803 6f4d00ee 2013-09-23 0intro blockPut(b);
804 6f4d00ee 2013-09-23 0intro b = bb;
805 6f4d00ee 2013-09-23 0intro }
806 6f4d00ee 2013-09-23 0intro b->pc = getcallerpc(&r);
807 6f4d00ee 2013-09-23 0intro return b;
808 6f4d00ee 2013-09-23 0intro Err:
809 6f4d00ee 2013-09-23 0intro blockPut(b);
810 6f4d00ee 2013-09-23 0intro return nil;
811 6f4d00ee 2013-09-23 0intro }
812 6f4d00ee 2013-09-23 0intro
813 6f4d00ee 2013-09-23 0intro Block*
814 6f4d00ee 2013-09-23 0intro sourceBlock(Source *r, ulong bn, int mode)
815 6f4d00ee 2013-09-23 0intro {
816 6f4d00ee 2013-09-23 0intro Block *b;
817 6f4d00ee 2013-09-23 0intro
818 6f4d00ee 2013-09-23 0intro b = _sourceBlock(r, bn, mode, 0, 0);
819 6f4d00ee 2013-09-23 0intro if(b)
820 6f4d00ee 2013-09-23 0intro b->pc = getcallerpc(&r);
821 6f4d00ee 2013-09-23 0intro return b;
822 6f4d00ee 2013-09-23 0intro }
823 6f4d00ee 2013-09-23 0intro
824 6f4d00ee 2013-09-23 0intro void
825 6f4d00ee 2013-09-23 0intro sourceClose(Source *r)
826 6f4d00ee 2013-09-23 0intro {
827 6f4d00ee 2013-09-23 0intro if(r == nil)
828 6f4d00ee 2013-09-23 0intro return;
829 4b576658 2013-09-23 0intro qlock(&r->lk);
830 6f4d00ee 2013-09-23 0intro r->ref--;
831 6f4d00ee 2013-09-23 0intro if(r->ref){
832 4b576658 2013-09-23 0intro qunlock(&r->lk);
833 6f4d00ee 2013-09-23 0intro return;
834 6f4d00ee 2013-09-23 0intro }
835 6f4d00ee 2013-09-23 0intro assert(r->ref == 0);
836 4b576658 2013-09-23 0intro qunlock(&r->lk);
837 6f4d00ee 2013-09-23 0intro if(r->parent)
838 6f4d00ee 2013-09-23 0intro sourceClose(r->parent);
839 6f4d00ee 2013-09-23 0intro memset(r, ~0, sizeof(*r));
840 4b576658 2013-09-23 0intro vtfree(r);
841 6f4d00ee 2013-09-23 0intro }
842 6f4d00ee 2013-09-23 0intro
843 6f4d00ee 2013-09-23 0intro /*
844 6f4d00ee 2013-09-23 0intro * Retrieve the block containing the entry for r.
845 6f4d00ee 2013-09-23 0intro * If a snapshot has happened, we might need
846 6f4d00ee 2013-09-23 0intro * to get a new copy of the block. We avoid this
847 6f4d00ee 2013-09-23 0intro * in the common case by caching the score for
848 6f4d00ee 2013-09-23 0intro * the block and the last epoch in which it was valid.
849 6f4d00ee 2013-09-23 0intro *
850 6f4d00ee 2013-09-23 0intro * We use r->mode to tell the difference between active
851 6f4d00ee 2013-09-23 0intro * file system sources (OReadWrite) and sources for the
852 6f4d00ee 2013-09-23 0intro * snapshot file system (OReadOnly).
853 6f4d00ee 2013-09-23 0intro */
854 6f4d00ee 2013-09-23 0intro static Block*
855 6f4d00ee 2013-09-23 0intro sourceLoadBlock(Source *r, int mode)
856 6f4d00ee 2013-09-23 0intro {
857 6f4d00ee 2013-09-23 0intro u32int addr;
858 6f4d00ee 2013-09-23 0intro Block *b;
859 4b576658 2013-09-23 0intro char e[ERRMAX];
860 6f4d00ee 2013-09-23 0intro
861 6f4d00ee 2013-09-23 0intro switch(r->mode){
862 6f4d00ee 2013-09-23 0intro default:
863 6f4d00ee 2013-09-23 0intro assert(0);
864 6f4d00ee 2013-09-23 0intro case OReadWrite:
865 6f4d00ee 2013-09-23 0intro assert(r->mode == OReadWrite);
866 6f4d00ee 2013-09-23 0intro /*
867 6f4d00ee 2013-09-23 0intro * This needn't be true -- we might bump the low epoch
868 6f4d00ee 2013-09-23 0intro * to reclaim some old blocks, but since this score is
869 6f4d00ee 2013-09-23 0intro * OReadWrite, the blocks must all still be open, so none
870 6f4d00ee 2013-09-23 0intro * are reclaimed. Thus it's okay that the epoch is so low.
871 6f4d00ee 2013-09-23 0intro * Proceed.
872 6f4d00ee 2013-09-23 0intro assert(r->epoch >= r->fs->elo);
873 6f4d00ee 2013-09-23 0intro */
874 6f4d00ee 2013-09-23 0intro if(r->epoch == r->fs->ehi){
875 6f4d00ee 2013-09-23 0intro b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite);
876 6f4d00ee 2013-09-23 0intro if(b == nil)
877 6f4d00ee 2013-09-23 0intro return nil;
878 6f4d00ee 2013-09-23 0intro assert(r->epoch == b->l.epoch);
879 6f4d00ee 2013-09-23 0intro return b;
880 6f4d00ee 2013-09-23 0intro }
881 6f4d00ee 2013-09-23 0intro assert(r->parent != nil);
882 6f4d00ee 2013-09-23 0intro if(!sourceLock(r->parent, OReadWrite))
883 6f4d00ee 2013-09-23 0intro return nil;
884 6f4d00ee 2013-09-23 0intro b = sourceBlock(r->parent, r->offset/r->epb, OReadWrite);
885 6f4d00ee 2013-09-23 0intro sourceUnlock(r->parent);
886 6f4d00ee 2013-09-23 0intro if(b == nil)
887 6f4d00ee 2013-09-23 0intro return nil;
888 6f4d00ee 2013-09-23 0intro assert(b->l.epoch == r->fs->ehi);
889 6f4d00ee 2013-09-23 0intro // fprint(2, "sourceLoadBlock %p %V => %V\n", r, r->score, b->score);
890 6f4d00ee 2013-09-23 0intro memmove(r->score, b->score, VtScoreSize);
891 6f4d00ee 2013-09-23 0intro r->scoreEpoch = b->l.epoch;
892 6f4d00ee 2013-09-23 0intro r->tag = b->l.tag;
893 6f4d00ee 2013-09-23 0intro r->epoch = r->fs->ehi;
894 6f4d00ee 2013-09-23 0intro return b;
895 6f4d00ee 2013-09-23 0intro
896 6f4d00ee 2013-09-23 0intro case OReadOnly:
897 6f4d00ee 2013-09-23 0intro addr = globalToLocal(r->score);
898 6f4d00ee 2013-09-23 0intro if(addr == NilBlock)
899 6f4d00ee 2013-09-23 0intro return cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, mode);
900 6f4d00ee 2013-09-23 0intro
901 6f4d00ee 2013-09-23 0intro b = cacheLocalData(r->fs->cache, addr, BtDir, r->tag, mode, r->scoreEpoch);
902 6f4d00ee 2013-09-23 0intro if(b)
903 6f4d00ee 2013-09-23 0intro return b;
904 6f4d00ee 2013-09-23 0intro
905 6f4d00ee 2013-09-23 0intro /*
906 6f4d00ee 2013-09-23 0intro * If it failed because the epochs don't match, the block has been
907 6f4d00ee 2013-09-23 0intro * archived and reclaimed. Rewalk from the parent and get the
908 6f4d00ee 2013-09-23 0intro * new pointer. This can't happen in the OReadWrite case
909 6f4d00ee 2013-09-23 0intro * above because blocks in the current epoch don't get
910 6f4d00ee 2013-09-23 0intro * reclaimed. The fact that we're OReadOnly means we're
911 6f4d00ee 2013-09-23 0intro * a snapshot. (Or else the file system is read-only, but then
912 6f4d00ee 2013-09-23 0intro * the archiver isn't going around deleting blocks.)
913 6f4d00ee 2013-09-23 0intro */
914 4b576658 2013-09-23 0intro rerrstr(e, sizeof e);
915 4b576658 2013-09-23 0intro if(strcmp(e, ELabelMismatch) == 0){
916 6f4d00ee 2013-09-23 0intro if(!sourceLock(r->parent, OReadOnly))
917 6f4d00ee 2013-09-23 0intro return nil;
918 6f4d00ee 2013-09-23 0intro b = sourceBlock(r->parent, r->offset/r->epb, OReadOnly);
919 6f4d00ee 2013-09-23 0intro sourceUnlock(r->parent);
920 6f4d00ee 2013-09-23 0intro if(b){
921 6f4d00ee 2013-09-23 0intro fprint(2, "sourceAlloc: lost %V found %V\n",
922 6f4d00ee 2013-09-23 0intro r->score, b->score);
923 6f4d00ee 2013-09-23 0intro memmove(r->score, b->score, VtScoreSize);
924 6f4d00ee 2013-09-23 0intro r->scoreEpoch = b->l.epoch;
925 6f4d00ee 2013-09-23 0intro return b;
926 6f4d00ee 2013-09-23 0intro }
927 6f4d00ee 2013-09-23 0intro }
928 6f4d00ee 2013-09-23 0intro return nil;
929 6f4d00ee 2013-09-23 0intro }
930 6f4d00ee 2013-09-23 0intro }
931 6f4d00ee 2013-09-23 0intro
932 6f4d00ee 2013-09-23 0intro int
933 6f4d00ee 2013-09-23 0intro sourceLock(Source *r, int mode)
934 6f4d00ee 2013-09-23 0intro {
935 6f4d00ee 2013-09-23 0intro Block *b;
936 6f4d00ee 2013-09-23 0intro
937 6f4d00ee 2013-09-23 0intro if(mode == -1)
938 6f4d00ee 2013-09-23 0intro mode = r->mode;
939 6f4d00ee 2013-09-23 0intro
940 6f4d00ee 2013-09-23 0intro b = sourceLoadBlock(r, mode);
941 6f4d00ee 2013-09-23 0intro if(b == nil)
942 6f4d00ee 2013-09-23 0intro return 0;
943 6f4d00ee 2013-09-23 0intro /*
944 6f4d00ee 2013-09-23 0intro * The fact that we are holding b serves as the
945 6f4d00ee 2013-09-23 0intro * lock entitling us to write to r->b.
946 6f4d00ee 2013-09-23 0intro */
947 6f4d00ee 2013-09-23 0intro assert(r->b == nil);
948 6f4d00ee 2013-09-23 0intro r->b = b;
949 6f4d00ee 2013-09-23 0intro if(r->mode == OReadWrite)
950 6f4d00ee 2013-09-23 0intro assert(r->epoch == r->b->l.epoch);
951 6f4d00ee 2013-09-23 0intro return 1;
952 6f4d00ee 2013-09-23 0intro }
953 6f4d00ee 2013-09-23 0intro
954 6f4d00ee 2013-09-23 0intro /*
955 6f4d00ee 2013-09-23 0intro * Lock two (usually sibling) sources. This needs special care
956 6f4d00ee 2013-09-23 0intro * because the Entries for both sources might be in the same block.
957 6f4d00ee 2013-09-23 0intro * We also try to lock blocks in left-to-right order within the tree.
958 6f4d00ee 2013-09-23 0intro */
959 6f4d00ee 2013-09-23 0intro int
960 6f4d00ee 2013-09-23 0intro sourceLock2(Source *r, Source *rr, int mode)
961 6f4d00ee 2013-09-23 0intro {
962 6f4d00ee 2013-09-23 0intro Block *b, *bb;
963 6f4d00ee 2013-09-23 0intro
964 6f4d00ee 2013-09-23 0intro if(rr == nil)
965 6f4d00ee 2013-09-23 0intro return sourceLock(r, mode);
966 6f4d00ee 2013-09-23 0intro
967 6f4d00ee 2013-09-23 0intro if(mode == -1)
968 6f4d00ee 2013-09-23 0intro mode = r->mode;
969 6f4d00ee 2013-09-23 0intro
970 6f4d00ee 2013-09-23 0intro if(r->parent==rr->parent && r->offset/r->epb == rr->offset/rr->epb){
971 6f4d00ee 2013-09-23 0intro b = sourceLoadBlock(r, mode);
972 6f4d00ee 2013-09-23 0intro if(b == nil)
973 6f4d00ee 2013-09-23 0intro return 0;
974 6f4d00ee 2013-09-23 0intro if(memcmp(r->score, rr->score, VtScoreSize) != 0){
975 6f4d00ee 2013-09-23 0intro memmove(rr->score, b->score, VtScoreSize);
976 6f4d00ee 2013-09-23 0intro rr->scoreEpoch = b->l.epoch;
977 6f4d00ee 2013-09-23 0intro rr->tag = b->l.tag;
978 6f4d00ee 2013-09-23 0intro rr->epoch = rr->fs->ehi;
979 6f4d00ee 2013-09-23 0intro }
980 6f4d00ee 2013-09-23 0intro blockDupLock(b);
981 6f4d00ee 2013-09-23 0intro bb = b;
982 6f4d00ee 2013-09-23 0intro }else if(r->parent==rr->parent || r->offset > rr->offset){
983 6f4d00ee 2013-09-23 0intro bb = sourceLoadBlock(rr, mode);
984 6f4d00ee 2013-09-23 0intro b = sourceLoadBlock(r, mode);
985 6f4d00ee 2013-09-23 0intro }else{
986 6f4d00ee 2013-09-23 0intro b = sourceLoadBlock(r, mode);
987 6f4d00ee 2013-09-23 0intro bb = sourceLoadBlock(rr, mode);
988 6f4d00ee 2013-09-23 0intro }
989 6f4d00ee 2013-09-23 0intro if(b == nil || bb == nil){
990 6f4d00ee 2013-09-23 0intro if(b)
991 6f4d00ee 2013-09-23 0intro blockPut(b);
992 6f4d00ee 2013-09-23 0intro if(bb)
993 6f4d00ee 2013-09-23 0intro blockPut(bb);
994 6f4d00ee 2013-09-23 0intro return 0;
995 6f4d00ee 2013-09-23 0intro }
996 6f4d00ee 2013-09-23 0intro
997 6f4d00ee 2013-09-23 0intro /*
998 6f4d00ee 2013-09-23 0intro * The fact that we are holding b and bb serves
999 6f4d00ee 2013-09-23 0intro * as the lock entitling us to write to r->b and rr->b.
1000 6f4d00ee 2013-09-23 0intro */
1001 6f4d00ee 2013-09-23 0intro r->b = b;
1002 6f4d00ee 2013-09-23 0intro rr->b = bb;
1003 6f4d00ee 2013-09-23 0intro return 1;
1004 6f4d00ee 2013-09-23 0intro }
1005 6f4d00ee 2013-09-23 0intro
1006 6f4d00ee 2013-09-23 0intro void
1007 6f4d00ee 2013-09-23 0intro sourceUnlock(Source *r)
1008 6f4d00ee 2013-09-23 0intro {
1009 6f4d00ee 2013-09-23 0intro Block *b;
1010 6f4d00ee 2013-09-23 0intro
1011 6f4d00ee 2013-09-23 0intro if(r->b == nil){
1012 6f4d00ee 2013-09-23 0intro fprint(2, "sourceUnlock: already unlocked\n");
1013 6f4d00ee 2013-09-23 0intro abort();
1014 6f4d00ee 2013-09-23 0intro }
1015 6f4d00ee 2013-09-23 0intro b = r->b;
1016 6f4d00ee 2013-09-23 0intro r->b = nil;
1017 6f4d00ee 2013-09-23 0intro blockPut(b);
1018 6f4d00ee 2013-09-23 0intro }
1019 6f4d00ee 2013-09-23 0intro
1020 6f4d00ee 2013-09-23 0intro static Block*
1021 6f4d00ee 2013-09-23 0intro sourceLoad(Source *r, Entry *e)
1022 6f4d00ee 2013-09-23 0intro {
1023 6f4d00ee 2013-09-23 0intro Block *b;
1024 6f4d00ee 2013-09-23 0intro
1025 6f4d00ee 2013-09-23 0intro assert(sourceIsLocked(r));
1026 6f4d00ee 2013-09-23 0intro b = r->b;
1027 6f4d00ee 2013-09-23 0intro if(!entryUnpack(e, b->data, r->offset % r->epb))
1028 6f4d00ee 2013-09-23 0intro return nil;
1029 6f4d00ee 2013-09-23 0intro if(e->gen != r->gen){
1030 4b576658 2013-09-23 0intro werrstr(ERemoved);
1031 6f4d00ee 2013-09-23 0intro return nil;
1032 6f4d00ee 2013-09-23 0intro }
1033 6f4d00ee 2013-09-23 0intro blockDupLock(b);
1034 6f4d00ee 2013-09-23 0intro return b;
1035 6f4d00ee 2013-09-23 0intro }
1036 6f4d00ee 2013-09-23 0intro
1037 6f4d00ee 2013-09-23 0intro static int
1038 6f4d00ee 2013-09-23 0intro sizeToDepth(uvlong s, int psize, int dsize)
1039 6f4d00ee 2013-09-23 0intro {
1040 6f4d00ee 2013-09-23 0intro int np;
1041 6f4d00ee 2013-09-23 0intro int d;
1042 6f4d00ee 2013-09-23 0intro
1043 6f4d00ee 2013-09-23 0intro /* determine pointer depth */
1044 6f4d00ee 2013-09-23 0intro np = psize/VtScoreSize;
1045 6f4d00ee 2013-09-23 0intro s = (s + dsize - 1)/dsize;
1046 6f4d00ee 2013-09-23 0intro for(d = 0; s > 1; d++)
1047 6f4d00ee 2013-09-23 0intro s = (s + np - 1)/np;
1048 6f4d00ee 2013-09-23 0intro return d;
1049 6f4d00ee 2013-09-23 0intro }
1050 6f4d00ee 2013-09-23 0intro
1051 6f4d00ee 2013-09-23 0intro static u32int
1052 6f4d00ee 2013-09-23 0intro tagGen(void)
1053 6f4d00ee 2013-09-23 0intro {
1054 6f4d00ee 2013-09-23 0intro u32int tag;
1055 6f4d00ee 2013-09-23 0intro
1056 6f4d00ee 2013-09-23 0intro for(;;){
1057 6f4d00ee 2013-09-23 0intro tag = lrand();
1058 6f4d00ee 2013-09-23 0intro if(tag >= UserTag)
1059 6f4d00ee 2013-09-23 0intro break;
1060 6f4d00ee 2013-09-23 0intro }
1061 6f4d00ee 2013-09-23 0intro return tag;
1062 6f4d00ee 2013-09-23 0intro }
1063 6f4d00ee 2013-09-23 0intro
1064 6f4d00ee 2013-09-23 0intro char *
1065 6f4d00ee 2013-09-23 0intro sourceName(Source *s)
1066 6f4d00ee 2013-09-23 0intro {
1067 6f4d00ee 2013-09-23 0intro return fileName(s->file);
1068 6f4d00ee 2013-09-23 0intro }