Blame


1 056fe1ba 2003-11-23 devnull /*
2 056fe1ba 2003-11-23 devnull * Manage tree of VtFiles stored in the block cache.
3 056fe1ba 2003-11-23 devnull *
4 056fe1ba 2003-11-23 devnull * The single point of truth for the info about the VtFiles themselves
5 056fe1ba 2003-11-23 devnull * is the block data. Because of this, there is no explicit locking of
6 056fe1ba 2003-11-23 devnull * VtFile structures, and indeed there may be more than one VtFile
7 fa325e9b 2020-01-10 cross * structure for a given Venti file. They synchronize through the
8 056fe1ba 2003-11-23 devnull * block cache.
9 056fe1ba 2003-11-23 devnull *
10 056fe1ba 2003-11-23 devnull * This is a bit simpler than fossil because there are no epochs
11 056fe1ba 2003-11-23 devnull * or tags or anything else. Just mutable local blocks and immutable
12 056fe1ba 2003-11-23 devnull * Venti blocks.
13 056fe1ba 2003-11-23 devnull */
14 056fe1ba 2003-11-23 devnull
15 056fe1ba 2003-11-23 devnull #include <u.h>
16 056fe1ba 2003-11-23 devnull #include <libc.h>
17 056fe1ba 2003-11-23 devnull #include <venti.h>
18 056fe1ba 2003-11-23 devnull
19 0dc99502 2005-01-14 devnull #define MaxBlock (1UL<<31)
20 056fe1ba 2003-11-23 devnull
21 056fe1ba 2003-11-23 devnull static char ENotDir[] = "walk in non-directory";
22 056fe1ba 2003-11-23 devnull static char ETooBig[] = "file too big";
23 e5d47e6e 2004-12-28 devnull /* static char EBadAddr[] = "bad address"; */
24 056fe1ba 2003-11-23 devnull static char ELabelMismatch[] = "label mismatch";
25 056fe1ba 2003-11-23 devnull
26 056fe1ba 2003-11-23 devnull static int sizetodepth(uvlong s, int psize, int dsize);
27 056fe1ba 2003-11-23 devnull static VtBlock *fileload(VtFile *r, VtEntry *e);
28 056fe1ba 2003-11-23 devnull static int shrinkdepth(VtFile*, VtBlock*, VtEntry*, int);
29 056fe1ba 2003-11-23 devnull static int shrinksize(VtFile*, VtEntry*, uvlong);
30 056fe1ba 2003-11-23 devnull static int growdepth(VtFile*, VtBlock*, VtEntry*, int);
31 056fe1ba 2003-11-23 devnull
32 056fe1ba 2003-11-23 devnull #define ISLOCKED(r) ((r)->b != nil)
33 056fe1ba 2003-11-23 devnull #define DEPTH(t) ((t)&VtTypeDepthMask)
34 056fe1ba 2003-11-23 devnull
35 056fe1ba 2003-11-23 devnull static VtFile *
36 056fe1ba 2003-11-23 devnull vtfilealloc(VtCache *c, VtBlock *b, VtFile *p, u32int offset, int mode)
37 056fe1ba 2003-11-23 devnull {
38 056fe1ba 2003-11-23 devnull int epb;
39 056fe1ba 2003-11-23 devnull VtEntry e;
40 056fe1ba 2003-11-23 devnull VtFile *r;
41 056fe1ba 2003-11-23 devnull
42 056fe1ba 2003-11-23 devnull assert(p==nil || ISLOCKED(p));
43 056fe1ba 2003-11-23 devnull
44 056fe1ba 2003-11-23 devnull if(p == nil){
45 056fe1ba 2003-11-23 devnull assert(offset == 0);
46 056fe1ba 2003-11-23 devnull epb = 1;
47 056fe1ba 2003-11-23 devnull }else
48 056fe1ba 2003-11-23 devnull epb = p->dsize / VtEntrySize;
49 056fe1ba 2003-11-23 devnull
50 23fb2edb 2005-07-24 devnull if(b->type != VtDirType){
51 23fb2edb 2005-07-24 devnull werrstr("bad block type %#uo", b->type);
52 23fb2edb 2005-07-24 devnull return nil;
53 23fb2edb 2005-07-24 devnull }
54 056fe1ba 2003-11-23 devnull
55 056fe1ba 2003-11-23 devnull /*
56 056fe1ba 2003-11-23 devnull * a non-active entry is the only thing that
57 056fe1ba 2003-11-23 devnull * can legitimately happen here. all the others
58 056fe1ba 2003-11-23 devnull * get prints.
59 056fe1ba 2003-11-23 devnull */
60 056fe1ba 2003-11-23 devnull if(vtentryunpack(&e, b->data, offset % epb) < 0){
61 23fb2edb 2005-07-24 devnull fprint(2, "vtentryunpack failed: %r (%.*H)\n", VtEntrySize, b->data+VtEntrySize*(offset%epb));
62 23fb2edb 2005-07-24 devnull return nil;
63 056fe1ba 2003-11-23 devnull }
64 056fe1ba 2003-11-23 devnull if(!(e.flags & VtEntryActive)){
65 23fb2edb 2005-07-24 devnull werrstr("entry not active");
66 23fb2edb 2005-07-24 devnull return nil;
67 056fe1ba 2003-11-23 devnull }
68 056fe1ba 2003-11-23 devnull
69 056fe1ba 2003-11-23 devnull if(DEPTH(e.type) < sizetodepth(e.size, e.psize, e.dsize)){
70 36c242dd 2011-11-08 rsc fprint(2, "depth %ud size %llud psize %lud dsize %lud\n",
71 056fe1ba 2003-11-23 devnull DEPTH(e.type), e.size, e.psize, e.dsize);
72 23fb2edb 2005-07-24 devnull werrstr("bad depth");
73 23fb2edb 2005-07-24 devnull return nil;
74 056fe1ba 2003-11-23 devnull }
75 056fe1ba 2003-11-23 devnull
76 056fe1ba 2003-11-23 devnull r = vtmallocz(sizeof(VtFile));
77 056fe1ba 2003-11-23 devnull r->c = c;
78 75d04888 2009-05-25 rsc r->bsize = b->size;
79 056fe1ba 2003-11-23 devnull r->mode = mode;
80 056fe1ba 2003-11-23 devnull r->dsize = e.dsize;
81 c1e6f642 2005-07-13 devnull r->psize = e.psize;
82 056fe1ba 2003-11-23 devnull r->gen = e.gen;
83 d23a617a 2004-03-15 devnull r->dir = (e.type & VtTypeBaseMask) == VtDirType;
84 056fe1ba 2003-11-23 devnull r->ref = 1;
85 056fe1ba 2003-11-23 devnull r->parent = p;
86 056fe1ba 2003-11-23 devnull if(p){
87 056fe1ba 2003-11-23 devnull qlock(&p->lk);
88 056fe1ba 2003-11-23 devnull assert(mode == VtOREAD || p->mode == VtORDWR);
89 056fe1ba 2003-11-23 devnull p->ref++;
90 056fe1ba 2003-11-23 devnull qunlock(&p->lk);
91 7cb74894 2004-06-17 devnull }else{
92 7cb74894 2004-06-17 devnull assert(b->addr != NilBlock);
93 7cb74894 2004-06-17 devnull r->local = 1;
94 056fe1ba 2003-11-23 devnull }
95 056fe1ba 2003-11-23 devnull memmove(r->score, b->score, VtScoreSize);
96 056fe1ba 2003-11-23 devnull r->offset = offset;
97 056fe1ba 2003-11-23 devnull r->epb = epb;
98 056fe1ba 2003-11-23 devnull
99 056fe1ba 2003-11-23 devnull return r;
100 056fe1ba 2003-11-23 devnull }
101 056fe1ba 2003-11-23 devnull
102 056fe1ba 2003-11-23 devnull VtFile *
103 056fe1ba 2003-11-23 devnull vtfileroot(VtCache *c, u32int addr, int mode)
104 056fe1ba 2003-11-23 devnull {
105 056fe1ba 2003-11-23 devnull VtFile *r;
106 056fe1ba 2003-11-23 devnull VtBlock *b;
107 056fe1ba 2003-11-23 devnull
108 056fe1ba 2003-11-23 devnull b = vtcachelocal(c, addr, VtDirType);
109 056fe1ba 2003-11-23 devnull if(b == nil)
110 056fe1ba 2003-11-23 devnull return nil;
111 056fe1ba 2003-11-23 devnull r = vtfilealloc(c, b, nil, 0, mode);
112 056fe1ba 2003-11-23 devnull vtblockput(b);
113 056fe1ba 2003-11-23 devnull return r;
114 056fe1ba 2003-11-23 devnull }
115 056fe1ba 2003-11-23 devnull
116 056fe1ba 2003-11-23 devnull VtFile*
117 056fe1ba 2003-11-23 devnull vtfileopenroot(VtCache *c, VtEntry *e)
118 056fe1ba 2003-11-23 devnull {
119 056fe1ba 2003-11-23 devnull VtBlock *b;
120 056fe1ba 2003-11-23 devnull VtFile *f;
121 056fe1ba 2003-11-23 devnull
122 75d04888 2009-05-25 rsc b = vtcacheallocblock(c, VtDirType, VtEntrySize);
123 056fe1ba 2003-11-23 devnull if(b == nil)
124 056fe1ba 2003-11-23 devnull return nil;
125 056fe1ba 2003-11-23 devnull
126 056fe1ba 2003-11-23 devnull vtentrypack(e, b->data, 0);
127 056fe1ba 2003-11-23 devnull f = vtfilealloc(c, b, nil, 0, VtORDWR);
128 056fe1ba 2003-11-23 devnull vtblockput(b);
129 056fe1ba 2003-11-23 devnull return f;
130 056fe1ba 2003-11-23 devnull }
131 056fe1ba 2003-11-23 devnull
132 056fe1ba 2003-11-23 devnull VtFile *
133 056fe1ba 2003-11-23 devnull vtfilecreateroot(VtCache *c, int psize, int dsize, int type)
134 056fe1ba 2003-11-23 devnull {
135 056fe1ba 2003-11-23 devnull VtEntry e;
136 056fe1ba 2003-11-23 devnull
137 056fe1ba 2003-11-23 devnull memset(&e, 0, sizeof e);
138 056fe1ba 2003-11-23 devnull e.flags = VtEntryActive;
139 056fe1ba 2003-11-23 devnull e.psize = psize;
140 056fe1ba 2003-11-23 devnull e.dsize = dsize;
141 d23a617a 2004-03-15 devnull e.type = type;
142 056fe1ba 2003-11-23 devnull memmove(e.score, vtzeroscore, VtScoreSize);
143 056fe1ba 2003-11-23 devnull
144 056fe1ba 2003-11-23 devnull return vtfileopenroot(c, &e);
145 056fe1ba 2003-11-23 devnull }
146 056fe1ba 2003-11-23 devnull
147 056fe1ba 2003-11-23 devnull VtFile *
148 056fe1ba 2003-11-23 devnull vtfileopen(VtFile *r, u32int offset, int mode)
149 056fe1ba 2003-11-23 devnull {
150 056fe1ba 2003-11-23 devnull ulong bn;
151 056fe1ba 2003-11-23 devnull VtBlock *b;
152 056fe1ba 2003-11-23 devnull
153 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
154 056fe1ba 2003-11-23 devnull if(!r->dir){
155 056fe1ba 2003-11-23 devnull werrstr(ENotDir);
156 056fe1ba 2003-11-23 devnull return nil;
157 056fe1ba 2003-11-23 devnull }
158 056fe1ba 2003-11-23 devnull
159 056fe1ba 2003-11-23 devnull bn = offset/(r->dsize/VtEntrySize);
160 056fe1ba 2003-11-23 devnull
161 056fe1ba 2003-11-23 devnull b = vtfileblock(r, bn, mode);
162 056fe1ba 2003-11-23 devnull if(b == nil)
163 056fe1ba 2003-11-23 devnull return nil;
164 056fe1ba 2003-11-23 devnull r = vtfilealloc(r->c, b, r, offset, mode);
165 056fe1ba 2003-11-23 devnull vtblockput(b);
166 056fe1ba 2003-11-23 devnull return r;
167 056fe1ba 2003-11-23 devnull }
168 056fe1ba 2003-11-23 devnull
169 23fb2edb 2005-07-24 devnull VtFile*
170 3082404e 2005-07-13 devnull vtfilecreate(VtFile *r, int psize, int dsize, int type)
171 056fe1ba 2003-11-23 devnull {
172 23fb2edb 2005-07-24 devnull return _vtfilecreate(r, -1, psize, dsize, type);
173 23fb2edb 2005-07-24 devnull }
174 23fb2edb 2005-07-24 devnull
175 23fb2edb 2005-07-24 devnull VtFile*
176 23fb2edb 2005-07-24 devnull _vtfilecreate(VtFile *r, int o, int psize, int dsize, int type)
177 23fb2edb 2005-07-24 devnull {
178 056fe1ba 2003-11-23 devnull int i;
179 056fe1ba 2003-11-23 devnull VtBlock *b;
180 056fe1ba 2003-11-23 devnull u32int bn, size;
181 056fe1ba 2003-11-23 devnull VtEntry e;
182 056fe1ba 2003-11-23 devnull int epb;
183 056fe1ba 2003-11-23 devnull VtFile *rr;
184 23fb2edb 2005-07-24 devnull u32int offset;
185 fa325e9b 2020-01-10 cross
186 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
187 3082404e 2005-07-13 devnull assert(type == VtDirType || type == VtDataType);
188 056fe1ba 2003-11-23 devnull
189 056fe1ba 2003-11-23 devnull if(!r->dir){
190 056fe1ba 2003-11-23 devnull werrstr(ENotDir);
191 056fe1ba 2003-11-23 devnull return nil;
192 056fe1ba 2003-11-23 devnull }
193 056fe1ba 2003-11-23 devnull
194 056fe1ba 2003-11-23 devnull epb = r->dsize/VtEntrySize;
195 056fe1ba 2003-11-23 devnull
196 056fe1ba 2003-11-23 devnull size = vtfilegetdirsize(r);
197 056fe1ba 2003-11-23 devnull /*
198 056fe1ba 2003-11-23 devnull * look at a random block to see if we can find an empty entry
199 056fe1ba 2003-11-23 devnull */
200 23fb2edb 2005-07-24 devnull if(o == -1){
201 23fb2edb 2005-07-24 devnull offset = lnrand(size+1);
202 23fb2edb 2005-07-24 devnull offset -= offset % epb;
203 23fb2edb 2005-07-24 devnull }else
204 23fb2edb 2005-07-24 devnull offset = o;
205 056fe1ba 2003-11-23 devnull
206 056fe1ba 2003-11-23 devnull /* try the given block and then try the last block */
207 056fe1ba 2003-11-23 devnull for(;;){
208 056fe1ba 2003-11-23 devnull bn = offset/epb;
209 056fe1ba 2003-11-23 devnull b = vtfileblock(r, bn, VtORDWR);
210 056fe1ba 2003-11-23 devnull if(b == nil)
211 056fe1ba 2003-11-23 devnull return nil;
212 056fe1ba 2003-11-23 devnull for(i=offset%r->epb; i<epb; i++){
213 056fe1ba 2003-11-23 devnull if(vtentryunpack(&e, b->data, i) < 0)
214 056fe1ba 2003-11-23 devnull continue;
215 056fe1ba 2003-11-23 devnull if((e.flags&VtEntryActive) == 0 && e.gen != ~0)
216 056fe1ba 2003-11-23 devnull goto Found;
217 056fe1ba 2003-11-23 devnull }
218 056fe1ba 2003-11-23 devnull vtblockput(b);
219 056fe1ba 2003-11-23 devnull if(offset == size){
220 056fe1ba 2003-11-23 devnull fprint(2, "vtfilecreate: cannot happen\n");
221 056fe1ba 2003-11-23 devnull werrstr("vtfilecreate: cannot happen");
222 056fe1ba 2003-11-23 devnull return nil;
223 056fe1ba 2003-11-23 devnull }
224 056fe1ba 2003-11-23 devnull offset = size;
225 056fe1ba 2003-11-23 devnull }
226 056fe1ba 2003-11-23 devnull
227 056fe1ba 2003-11-23 devnull Found:
228 056fe1ba 2003-11-23 devnull /* found an entry - gen already set */
229 056fe1ba 2003-11-23 devnull e.psize = psize;
230 056fe1ba 2003-11-23 devnull e.dsize = dsize;
231 056fe1ba 2003-11-23 devnull e.flags = VtEntryActive;
232 3082404e 2005-07-13 devnull e.type = type;
233 056fe1ba 2003-11-23 devnull e.size = 0;
234 056fe1ba 2003-11-23 devnull memmove(e.score, vtzeroscore, VtScoreSize);
235 056fe1ba 2003-11-23 devnull vtentrypack(&e, b->data, i);
236 056fe1ba 2003-11-23 devnull
237 056fe1ba 2003-11-23 devnull offset = bn*epb + i;
238 056fe1ba 2003-11-23 devnull if(offset+1 > size){
239 056fe1ba 2003-11-23 devnull if(vtfilesetdirsize(r, offset+1) < 0){
240 056fe1ba 2003-11-23 devnull vtblockput(b);
241 056fe1ba 2003-11-23 devnull return nil;
242 056fe1ba 2003-11-23 devnull }
243 056fe1ba 2003-11-23 devnull }
244 056fe1ba 2003-11-23 devnull
245 056fe1ba 2003-11-23 devnull rr = vtfilealloc(r->c, b, r, offset, VtORDWR);
246 056fe1ba 2003-11-23 devnull vtblockput(b);
247 056fe1ba 2003-11-23 devnull return rr;
248 056fe1ba 2003-11-23 devnull }
249 056fe1ba 2003-11-23 devnull
250 056fe1ba 2003-11-23 devnull static int
251 056fe1ba 2003-11-23 devnull vtfilekill(VtFile *r, int doremove)
252 056fe1ba 2003-11-23 devnull {
253 056fe1ba 2003-11-23 devnull VtEntry e;
254 056fe1ba 2003-11-23 devnull VtBlock *b;
255 056fe1ba 2003-11-23 devnull
256 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
257 056fe1ba 2003-11-23 devnull b = fileload(r, &e);
258 056fe1ba 2003-11-23 devnull if(b == nil)
259 056fe1ba 2003-11-23 devnull return -1;
260 056fe1ba 2003-11-23 devnull
261 056fe1ba 2003-11-23 devnull if(doremove==0 && e.size == 0){
262 056fe1ba 2003-11-23 devnull /* already truncated */
263 056fe1ba 2003-11-23 devnull vtblockput(b);
264 056fe1ba 2003-11-23 devnull return 0;
265 056fe1ba 2003-11-23 devnull }
266 056fe1ba 2003-11-23 devnull
267 056fe1ba 2003-11-23 devnull if(doremove){
268 056fe1ba 2003-11-23 devnull if(e.gen != ~0)
269 056fe1ba 2003-11-23 devnull e.gen++;
270 056fe1ba 2003-11-23 devnull e.dsize = 0;
271 056fe1ba 2003-11-23 devnull e.psize = 0;
272 056fe1ba 2003-11-23 devnull e.flags = 0;
273 056fe1ba 2003-11-23 devnull }else
274 056fe1ba 2003-11-23 devnull e.flags &= ~VtEntryLocal;
275 056fe1ba 2003-11-23 devnull e.type = 0;
276 056fe1ba 2003-11-23 devnull e.size = 0;
277 056fe1ba 2003-11-23 devnull memmove(e.score, vtzeroscore, VtScoreSize);
278 056fe1ba 2003-11-23 devnull vtentrypack(&e, b->data, r->offset % r->epb);
279 056fe1ba 2003-11-23 devnull vtblockput(b);
280 056fe1ba 2003-11-23 devnull
281 056fe1ba 2003-11-23 devnull if(doremove){
282 056fe1ba 2003-11-23 devnull vtfileunlock(r);
283 056fe1ba 2003-11-23 devnull vtfileclose(r);
284 056fe1ba 2003-11-23 devnull }
285 056fe1ba 2003-11-23 devnull
286 056fe1ba 2003-11-23 devnull return 0;
287 056fe1ba 2003-11-23 devnull }
288 056fe1ba 2003-11-23 devnull
289 056fe1ba 2003-11-23 devnull int
290 056fe1ba 2003-11-23 devnull vtfileremove(VtFile *r)
291 056fe1ba 2003-11-23 devnull {
292 056fe1ba 2003-11-23 devnull return vtfilekill(r, 1);
293 056fe1ba 2003-11-23 devnull }
294 056fe1ba 2003-11-23 devnull
295 056fe1ba 2003-11-23 devnull int
296 056fe1ba 2003-11-23 devnull vtfiletruncate(VtFile *r)
297 056fe1ba 2003-11-23 devnull {
298 056fe1ba 2003-11-23 devnull return vtfilekill(r, 0);
299 056fe1ba 2003-11-23 devnull }
300 056fe1ba 2003-11-23 devnull
301 056fe1ba 2003-11-23 devnull uvlong
302 056fe1ba 2003-11-23 devnull vtfilegetsize(VtFile *r)
303 056fe1ba 2003-11-23 devnull {
304 056fe1ba 2003-11-23 devnull VtEntry e;
305 056fe1ba 2003-11-23 devnull VtBlock *b;
306 056fe1ba 2003-11-23 devnull
307 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
308 056fe1ba 2003-11-23 devnull b = fileload(r, &e);
309 056fe1ba 2003-11-23 devnull if(b == nil)
310 056fe1ba 2003-11-23 devnull return ~(uvlong)0;
311 056fe1ba 2003-11-23 devnull vtblockput(b);
312 056fe1ba 2003-11-23 devnull
313 056fe1ba 2003-11-23 devnull return e.size;
314 056fe1ba 2003-11-23 devnull }
315 056fe1ba 2003-11-23 devnull
316 056fe1ba 2003-11-23 devnull static int
317 056fe1ba 2003-11-23 devnull shrinksize(VtFile *r, VtEntry *e, uvlong size)
318 056fe1ba 2003-11-23 devnull {
319 75d04888 2009-05-25 rsc int i, depth, bsiz, type, isdir, ppb;
320 056fe1ba 2003-11-23 devnull uvlong ptrsz;
321 056fe1ba 2003-11-23 devnull uchar score[VtScoreSize];
322 056fe1ba 2003-11-23 devnull VtBlock *b;
323 056fe1ba 2003-11-23 devnull
324 75d04888 2009-05-25 rsc b = vtcacheglobal(r->c, e->score, e->type, r->dsize);
325 056fe1ba 2003-11-23 devnull if(b == nil)
326 056fe1ba 2003-11-23 devnull return -1;
327 056fe1ba 2003-11-23 devnull
328 056fe1ba 2003-11-23 devnull ptrsz = e->dsize;
329 056fe1ba 2003-11-23 devnull ppb = e->psize/VtScoreSize;
330 056fe1ba 2003-11-23 devnull type = e->type;
331 056fe1ba 2003-11-23 devnull depth = DEPTH(type);
332 056fe1ba 2003-11-23 devnull for(i=0; i+1<depth; i++)
333 056fe1ba 2003-11-23 devnull ptrsz *= ppb;
334 056fe1ba 2003-11-23 devnull
335 056fe1ba 2003-11-23 devnull isdir = r->dir;
336 589ae3a3 2008-10-26 rsc while(DEPTH(type) > 0){
337 056fe1ba 2003-11-23 devnull if(b->addr == NilBlock){
338 056fe1ba 2003-11-23 devnull /* not worth copying the block just so we can zero some of it */
339 056fe1ba 2003-11-23 devnull vtblockput(b);
340 056fe1ba 2003-11-23 devnull return -1;
341 056fe1ba 2003-11-23 devnull }
342 056fe1ba 2003-11-23 devnull
343 056fe1ba 2003-11-23 devnull /*
344 056fe1ba 2003-11-23 devnull * invariant: each pointer in the tree rooted at b accounts for ptrsz bytes
345 056fe1ba 2003-11-23 devnull */
346 056fe1ba 2003-11-23 devnull
347 056fe1ba 2003-11-23 devnull /* zero the pointers to unnecessary blocks */
348 056fe1ba 2003-11-23 devnull i = (size+ptrsz-1)/ptrsz;
349 056fe1ba 2003-11-23 devnull for(; i<ppb; i++)
350 056fe1ba 2003-11-23 devnull memmove(b->data+i*VtScoreSize, vtzeroscore, VtScoreSize);
351 056fe1ba 2003-11-23 devnull
352 056fe1ba 2003-11-23 devnull /* recurse (go around again) on the partially necessary block */
353 056fe1ba 2003-11-23 devnull i = size/ptrsz;
354 056fe1ba 2003-11-23 devnull size = size%ptrsz;
355 056fe1ba 2003-11-23 devnull if(size == 0){
356 056fe1ba 2003-11-23 devnull vtblockput(b);
357 056fe1ba 2003-11-23 devnull return 0;
358 056fe1ba 2003-11-23 devnull }
359 056fe1ba 2003-11-23 devnull ptrsz /= ppb;
360 056fe1ba 2003-11-23 devnull type--;
361 056fe1ba 2003-11-23 devnull memmove(score, b->data+i*VtScoreSize, VtScoreSize);
362 056fe1ba 2003-11-23 devnull vtblockput(b);
363 75d04888 2009-05-25 rsc if(type == VtDataType || type == VtDirType)
364 75d04888 2009-05-25 rsc bsiz = r->dsize;
365 75d04888 2009-05-25 rsc else
366 75d04888 2009-05-25 rsc bsiz = r->psize;
367 75d04888 2009-05-25 rsc b = vtcacheglobal(r->c, score, type, bsiz);
368 056fe1ba 2003-11-23 devnull if(b == nil)
369 056fe1ba 2003-11-23 devnull return -1;
370 056fe1ba 2003-11-23 devnull }
371 056fe1ba 2003-11-23 devnull
372 056fe1ba 2003-11-23 devnull if(b->addr == NilBlock){
373 056fe1ba 2003-11-23 devnull vtblockput(b);
374 056fe1ba 2003-11-23 devnull return -1;
375 056fe1ba 2003-11-23 devnull }
376 056fe1ba 2003-11-23 devnull
377 056fe1ba 2003-11-23 devnull /*
378 056fe1ba 2003-11-23 devnull * No one ever truncates BtDir blocks.
379 056fe1ba 2003-11-23 devnull */
380 056fe1ba 2003-11-23 devnull if(depth==0 && !isdir && e->dsize > size)
381 056fe1ba 2003-11-23 devnull memset(b->data+size, 0, e->dsize-size);
382 056fe1ba 2003-11-23 devnull vtblockput(b);
383 056fe1ba 2003-11-23 devnull return 0;
384 056fe1ba 2003-11-23 devnull }
385 056fe1ba 2003-11-23 devnull
386 056fe1ba 2003-11-23 devnull int
387 3f6a501b 2005-12-30 devnull vtfilesetsize(VtFile *r, u64int size)
388 056fe1ba 2003-11-23 devnull {
389 056fe1ba 2003-11-23 devnull int depth, edepth;
390 056fe1ba 2003-11-23 devnull VtEntry e;
391 056fe1ba 2003-11-23 devnull VtBlock *b;
392 056fe1ba 2003-11-23 devnull
393 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
394 056fe1ba 2003-11-23 devnull if(size == 0)
395 056fe1ba 2003-11-23 devnull return vtfiletruncate(r);
396 056fe1ba 2003-11-23 devnull
397 056fe1ba 2003-11-23 devnull if(size > VtMaxFileSize || size > ((uvlong)MaxBlock)*r->dsize){
398 056fe1ba 2003-11-23 devnull werrstr(ETooBig);
399 056fe1ba 2003-11-23 devnull return -1;
400 056fe1ba 2003-11-23 devnull }
401 056fe1ba 2003-11-23 devnull
402 056fe1ba 2003-11-23 devnull b = fileload(r, &e);
403 056fe1ba 2003-11-23 devnull if(b == nil)
404 056fe1ba 2003-11-23 devnull return -1;
405 056fe1ba 2003-11-23 devnull
406 056fe1ba 2003-11-23 devnull /* quick out */
407 056fe1ba 2003-11-23 devnull if(e.size == size){
408 056fe1ba 2003-11-23 devnull vtblockput(b);
409 056fe1ba 2003-11-23 devnull return 0;
410 056fe1ba 2003-11-23 devnull }
411 056fe1ba 2003-11-23 devnull
412 056fe1ba 2003-11-23 devnull depth = sizetodepth(size, e.psize, e.dsize);
413 056fe1ba 2003-11-23 devnull edepth = DEPTH(e.type);
414 056fe1ba 2003-11-23 devnull if(depth < edepth){
415 056fe1ba 2003-11-23 devnull if(shrinkdepth(r, b, &e, depth) < 0){
416 056fe1ba 2003-11-23 devnull vtblockput(b);
417 056fe1ba 2003-11-23 devnull return -1;
418 056fe1ba 2003-11-23 devnull }
419 056fe1ba 2003-11-23 devnull }else if(depth > edepth){
420 056fe1ba 2003-11-23 devnull if(growdepth(r, b, &e, depth) < 0){
421 056fe1ba 2003-11-23 devnull vtblockput(b);
422 056fe1ba 2003-11-23 devnull return -1;
423 056fe1ba 2003-11-23 devnull }
424 056fe1ba 2003-11-23 devnull }
425 056fe1ba 2003-11-23 devnull
426 056fe1ba 2003-11-23 devnull if(size < e.size)
427 056fe1ba 2003-11-23 devnull shrinksize(r, &e, size);
428 056fe1ba 2003-11-23 devnull
429 056fe1ba 2003-11-23 devnull e.size = size;
430 056fe1ba 2003-11-23 devnull vtentrypack(&e, b->data, r->offset % r->epb);
431 056fe1ba 2003-11-23 devnull vtblockput(b);
432 056fe1ba 2003-11-23 devnull
433 056fe1ba 2003-11-23 devnull return 0;
434 056fe1ba 2003-11-23 devnull }
435 056fe1ba 2003-11-23 devnull
436 056fe1ba 2003-11-23 devnull int
437 056fe1ba 2003-11-23 devnull vtfilesetdirsize(VtFile *r, u32int ds)
438 056fe1ba 2003-11-23 devnull {
439 056fe1ba 2003-11-23 devnull uvlong size;
440 056fe1ba 2003-11-23 devnull int epb;
441 056fe1ba 2003-11-23 devnull
442 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
443 056fe1ba 2003-11-23 devnull epb = r->dsize/VtEntrySize;
444 056fe1ba 2003-11-23 devnull
445 056fe1ba 2003-11-23 devnull size = (uvlong)r->dsize*(ds/epb);
446 056fe1ba 2003-11-23 devnull size += VtEntrySize*(ds%epb);
447 056fe1ba 2003-11-23 devnull return vtfilesetsize(r, size);
448 056fe1ba 2003-11-23 devnull }
449 056fe1ba 2003-11-23 devnull
450 056fe1ba 2003-11-23 devnull u32int
451 056fe1ba 2003-11-23 devnull vtfilegetdirsize(VtFile *r)
452 056fe1ba 2003-11-23 devnull {
453 056fe1ba 2003-11-23 devnull ulong ds;
454 056fe1ba 2003-11-23 devnull uvlong size;
455 056fe1ba 2003-11-23 devnull int epb;
456 056fe1ba 2003-11-23 devnull
457 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
458 056fe1ba 2003-11-23 devnull epb = r->dsize/VtEntrySize;
459 056fe1ba 2003-11-23 devnull
460 056fe1ba 2003-11-23 devnull size = vtfilegetsize(r);
461 056fe1ba 2003-11-23 devnull ds = epb*(size/r->dsize);
462 056fe1ba 2003-11-23 devnull ds += (size%r->dsize)/VtEntrySize;
463 056fe1ba 2003-11-23 devnull return ds;
464 056fe1ba 2003-11-23 devnull }
465 056fe1ba 2003-11-23 devnull
466 056fe1ba 2003-11-23 devnull int
467 056fe1ba 2003-11-23 devnull vtfilegetentry(VtFile *r, VtEntry *e)
468 056fe1ba 2003-11-23 devnull {
469 056fe1ba 2003-11-23 devnull VtBlock *b;
470 056fe1ba 2003-11-23 devnull
471 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
472 056fe1ba 2003-11-23 devnull b = fileload(r, e);
473 056fe1ba 2003-11-23 devnull if(b == nil)
474 056fe1ba 2003-11-23 devnull return -1;
475 056fe1ba 2003-11-23 devnull vtblockput(b);
476 056fe1ba 2003-11-23 devnull
477 056fe1ba 2003-11-23 devnull return 0;
478 056fe1ba 2003-11-23 devnull }
479 056fe1ba 2003-11-23 devnull
480 056fe1ba 2003-11-23 devnull int
481 056fe1ba 2003-11-23 devnull vtfilesetentry(VtFile *r, VtEntry *e)
482 056fe1ba 2003-11-23 devnull {
483 056fe1ba 2003-11-23 devnull VtBlock *b;
484 056fe1ba 2003-11-23 devnull VtEntry ee;
485 056fe1ba 2003-11-23 devnull
486 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
487 056fe1ba 2003-11-23 devnull b = fileload(r, &ee);
488 056fe1ba 2003-11-23 devnull if(b == nil)
489 056fe1ba 2003-11-23 devnull return -1;
490 056fe1ba 2003-11-23 devnull vtentrypack(e, b->data, r->offset % r->epb);
491 056fe1ba 2003-11-23 devnull vtblockput(b);
492 056fe1ba 2003-11-23 devnull return 0;
493 056fe1ba 2003-11-23 devnull }
494 056fe1ba 2003-11-23 devnull
495 056fe1ba 2003-11-23 devnull static VtBlock *
496 75d04888 2009-05-25 rsc blockwalk(VtFile *r, VtBlock *p, int index, VtCache *c, int mode, VtEntry *e)
497 056fe1ba 2003-11-23 devnull {
498 056fe1ba 2003-11-23 devnull VtBlock *b;
499 75d04888 2009-05-25 rsc int type, size;
500 056fe1ba 2003-11-23 devnull uchar *score;
501 056fe1ba 2003-11-23 devnull
502 056fe1ba 2003-11-23 devnull switch(p->type){
503 056fe1ba 2003-11-23 devnull case VtDataType:
504 056fe1ba 2003-11-23 devnull assert(0);
505 056fe1ba 2003-11-23 devnull case VtDirType:
506 056fe1ba 2003-11-23 devnull type = e->type;
507 056fe1ba 2003-11-23 devnull score = e->score;
508 056fe1ba 2003-11-23 devnull break;
509 056fe1ba 2003-11-23 devnull default:
510 056fe1ba 2003-11-23 devnull type = p->type - 1;
511 056fe1ba 2003-11-23 devnull score = p->data+index*VtScoreSize;
512 056fe1ba 2003-11-23 devnull break;
513 056fe1ba 2003-11-23 devnull }
514 cbeb0b26 2006-04-01 devnull /*print("walk from %V/%d ty %d to %V ty %d\n", p->score, index, p->type, score, type); */
515 056fe1ba 2003-11-23 devnull
516 75d04888 2009-05-25 rsc if(type == VtDirType || type == VtDataType)
517 75d04888 2009-05-25 rsc size = r->dsize;
518 75d04888 2009-05-25 rsc else
519 75d04888 2009-05-25 rsc size = r->psize;
520 056fe1ba 2003-11-23 devnull if(mode == VtOWRITE && vtglobaltolocal(score) == NilBlock){
521 75d04888 2009-05-25 rsc b = vtcacheallocblock(c, type, size);
522 056fe1ba 2003-11-23 devnull if(b)
523 056fe1ba 2003-11-23 devnull goto HaveCopy;
524 056fe1ba 2003-11-23 devnull }else
525 75d04888 2009-05-25 rsc b = vtcacheglobal(c, score, type, size);
526 056fe1ba 2003-11-23 devnull
527 056fe1ba 2003-11-23 devnull if(b == nil || mode == VtOREAD)
528 056fe1ba 2003-11-23 devnull return b;
529 056fe1ba 2003-11-23 devnull
530 056fe1ba 2003-11-23 devnull if(vtglobaltolocal(b->score) != NilBlock)
531 056fe1ba 2003-11-23 devnull return b;
532 056fe1ba 2003-11-23 devnull
533 056fe1ba 2003-11-23 devnull /*
534 056fe1ba 2003-11-23 devnull * Copy on write.
535 056fe1ba 2003-11-23 devnull */
536 056fe1ba 2003-11-23 devnull e->flags |= VtEntryLocal;
537 056fe1ba 2003-11-23 devnull
538 056fe1ba 2003-11-23 devnull b = vtblockcopy(b/*, e->tag, fs->ehi, fs->elo*/);
539 056fe1ba 2003-11-23 devnull if(b == nil)
540 056fe1ba 2003-11-23 devnull return nil;
541 056fe1ba 2003-11-23 devnull
542 056fe1ba 2003-11-23 devnull HaveCopy:
543 056fe1ba 2003-11-23 devnull if(p->type == VtDirType){
544 056fe1ba 2003-11-23 devnull memmove(e->score, b->score, VtScoreSize);
545 056fe1ba 2003-11-23 devnull vtentrypack(e, p->data, index);
546 056fe1ba 2003-11-23 devnull }else{
547 056fe1ba 2003-11-23 devnull memmove(p->data+index*VtScoreSize, b->score, VtScoreSize);
548 056fe1ba 2003-11-23 devnull }
549 056fe1ba 2003-11-23 devnull return b;
550 056fe1ba 2003-11-23 devnull }
551 056fe1ba 2003-11-23 devnull
552 056fe1ba 2003-11-23 devnull /*
553 056fe1ba 2003-11-23 devnull * Change the depth of the VtFile r.
554 056fe1ba 2003-11-23 devnull * The entry e for r is contained in block p.
555 056fe1ba 2003-11-23 devnull */
556 056fe1ba 2003-11-23 devnull static int
557 056fe1ba 2003-11-23 devnull growdepth(VtFile *r, VtBlock *p, VtEntry *e, int depth)
558 056fe1ba 2003-11-23 devnull {
559 056fe1ba 2003-11-23 devnull VtBlock *b, *bb;
560 056fe1ba 2003-11-23 devnull
561 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
562 056fe1ba 2003-11-23 devnull assert(depth <= VtPointerDepth);
563 056fe1ba 2003-11-23 devnull
564 75d04888 2009-05-25 rsc b = vtcacheglobal(r->c, e->score, e->type, r->dsize);
565 056fe1ba 2003-11-23 devnull if(b == nil)
566 056fe1ba 2003-11-23 devnull return -1;
567 056fe1ba 2003-11-23 devnull
568 056fe1ba 2003-11-23 devnull /*
569 056fe1ba 2003-11-23 devnull * Keep adding layers until we get to the right depth
570 056fe1ba 2003-11-23 devnull * or an error occurs.
571 056fe1ba 2003-11-23 devnull */
572 056fe1ba 2003-11-23 devnull while(DEPTH(e->type) < depth){
573 75d04888 2009-05-25 rsc bb = vtcacheallocblock(r->c, e->type+1, r->psize);
574 056fe1ba 2003-11-23 devnull if(bb == nil)
575 056fe1ba 2003-11-23 devnull break;
576 056fe1ba 2003-11-23 devnull memmove(bb->data, b->score, VtScoreSize);
577 fa325e9b 2020-01-10 cross memmove(e->score, bb->score, VtScoreSize);
578 056fe1ba 2003-11-23 devnull e->type++;
579 056fe1ba 2003-11-23 devnull e->flags |= VtEntryLocal;
580 056fe1ba 2003-11-23 devnull vtblockput(b);
581 056fe1ba 2003-11-23 devnull b = bb;
582 056fe1ba 2003-11-23 devnull }
583 056fe1ba 2003-11-23 devnull
584 056fe1ba 2003-11-23 devnull vtentrypack(e, p->data, r->offset % r->epb);
585 056fe1ba 2003-11-23 devnull vtblockput(b);
586 056fe1ba 2003-11-23 devnull
587 056fe1ba 2003-11-23 devnull if(DEPTH(e->type) == depth)
588 056fe1ba 2003-11-23 devnull return 0;
589 056fe1ba 2003-11-23 devnull return -1;
590 056fe1ba 2003-11-23 devnull }
591 056fe1ba 2003-11-23 devnull
592 056fe1ba 2003-11-23 devnull static int
593 056fe1ba 2003-11-23 devnull shrinkdepth(VtFile *r, VtBlock *p, VtEntry *e, int depth)
594 056fe1ba 2003-11-23 devnull {
595 056fe1ba 2003-11-23 devnull VtBlock *b, *nb, *ob, *rb;
596 056fe1ba 2003-11-23 devnull
597 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
598 056fe1ba 2003-11-23 devnull assert(depth <= VtPointerDepth);
599 056fe1ba 2003-11-23 devnull
600 75d04888 2009-05-25 rsc rb = vtcacheglobal(r->c, e->score, e->type, r->psize);
601 056fe1ba 2003-11-23 devnull if(rb == nil)
602 e9b70a5f 2008-06-15 rsc return -1;
603 056fe1ba 2003-11-23 devnull
604 056fe1ba 2003-11-23 devnull /*
605 056fe1ba 2003-11-23 devnull * Walk down to the new root block.
606 056fe1ba 2003-11-23 devnull * We may stop early, but something is better than nothing.
607 056fe1ba 2003-11-23 devnull */
608 056fe1ba 2003-11-23 devnull
609 056fe1ba 2003-11-23 devnull ob = nil;
610 056fe1ba 2003-11-23 devnull b = rb;
611 056fe1ba 2003-11-23 devnull for(; DEPTH(e->type) > depth; e->type--){
612 75d04888 2009-05-25 rsc nb = vtcacheglobal(r->c, b->data, e->type-1, r->psize);
613 056fe1ba 2003-11-23 devnull if(nb == nil)
614 056fe1ba 2003-11-23 devnull break;
615 056fe1ba 2003-11-23 devnull if(ob!=nil && ob!=rb)
616 056fe1ba 2003-11-23 devnull vtblockput(ob);
617 056fe1ba 2003-11-23 devnull ob = b;
618 056fe1ba 2003-11-23 devnull b = nb;
619 056fe1ba 2003-11-23 devnull }
620 056fe1ba 2003-11-23 devnull
621 056fe1ba 2003-11-23 devnull if(b == rb){
622 056fe1ba 2003-11-23 devnull vtblockput(rb);
623 056fe1ba 2003-11-23 devnull return 0;
624 056fe1ba 2003-11-23 devnull }
625 056fe1ba 2003-11-23 devnull
626 056fe1ba 2003-11-23 devnull /*
627 056fe1ba 2003-11-23 devnull * Right now, e points at the root block rb, b is the new root block,
628 056fe1ba 2003-11-23 devnull * and ob points at b. To update:
629 056fe1ba 2003-11-23 devnull *
630 056fe1ba 2003-11-23 devnull * (i) change e to point at b
631 056fe1ba 2003-11-23 devnull * (ii) zero the pointer ob -> b
632 056fe1ba 2003-11-23 devnull * (iii) free the root block
633 056fe1ba 2003-11-23 devnull *
634 056fe1ba 2003-11-23 devnull * p (the block containing e) must be written before
635 056fe1ba 2003-11-23 devnull * anything else.
636 056fe1ba 2003-11-23 devnull */
637 056fe1ba 2003-11-23 devnull
638 056fe1ba 2003-11-23 devnull /* (i) */
639 056fe1ba 2003-11-23 devnull memmove(e->score, b->score, VtScoreSize);
640 056fe1ba 2003-11-23 devnull vtentrypack(e, p->data, r->offset % r->epb);
641 056fe1ba 2003-11-23 devnull
642 056fe1ba 2003-11-23 devnull /* (ii) */
643 056fe1ba 2003-11-23 devnull memmove(ob->data, vtzeroscore, VtScoreSize);
644 056fe1ba 2003-11-23 devnull
645 056fe1ba 2003-11-23 devnull /* (iii) */
646 056fe1ba 2003-11-23 devnull vtblockput(rb);
647 056fe1ba 2003-11-23 devnull if(ob!=nil && ob!=rb)
648 056fe1ba 2003-11-23 devnull vtblockput(ob);
649 056fe1ba 2003-11-23 devnull vtblockput(b);
650 056fe1ba 2003-11-23 devnull
651 056fe1ba 2003-11-23 devnull if(DEPTH(e->type) == depth)
652 056fe1ba 2003-11-23 devnull return 0;
653 056fe1ba 2003-11-23 devnull return -1;
654 056fe1ba 2003-11-23 devnull }
655 056fe1ba 2003-11-23 devnull
656 056fe1ba 2003-11-23 devnull static int
657 056fe1ba 2003-11-23 devnull mkindices(VtEntry *e, u32int bn, int *index)
658 056fe1ba 2003-11-23 devnull {
659 056fe1ba 2003-11-23 devnull int i, np;
660 056fe1ba 2003-11-23 devnull
661 59a96820 2004-06-17 devnull memset(index, 0, (VtPointerDepth+1)*sizeof(int));
662 056fe1ba 2003-11-23 devnull
663 056fe1ba 2003-11-23 devnull np = e->psize/VtScoreSize;
664 056fe1ba 2003-11-23 devnull for(i=0; bn > 0; i++){
665 056fe1ba 2003-11-23 devnull if(i >= VtPointerDepth){
666 d23a617a 2004-03-15 devnull werrstr("bad address 0x%lux", (ulong)bn);
667 056fe1ba 2003-11-23 devnull return -1;
668 056fe1ba 2003-11-23 devnull }
669 056fe1ba 2003-11-23 devnull index[i] = bn % np;
670 056fe1ba 2003-11-23 devnull bn /= np;
671 056fe1ba 2003-11-23 devnull }
672 056fe1ba 2003-11-23 devnull return i;
673 056fe1ba 2003-11-23 devnull }
674 fa325e9b 2020-01-10 cross
675 056fe1ba 2003-11-23 devnull VtBlock *
676 056fe1ba 2003-11-23 devnull vtfileblock(VtFile *r, u32int bn, int mode)
677 056fe1ba 2003-11-23 devnull {
678 056fe1ba 2003-11-23 devnull VtBlock *b, *bb;
679 056fe1ba 2003-11-23 devnull int index[VtPointerDepth+1];
680 056fe1ba 2003-11-23 devnull VtEntry e;
681 056fe1ba 2003-11-23 devnull int i;
682 056fe1ba 2003-11-23 devnull int m;
683 056fe1ba 2003-11-23 devnull
684 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
685 056fe1ba 2003-11-23 devnull assert(bn != NilBlock);
686 056fe1ba 2003-11-23 devnull
687 056fe1ba 2003-11-23 devnull b = fileload(r, &e);
688 056fe1ba 2003-11-23 devnull if(b == nil)
689 056fe1ba 2003-11-23 devnull return nil;
690 056fe1ba 2003-11-23 devnull
691 056fe1ba 2003-11-23 devnull i = mkindices(&e, bn, index);
692 056fe1ba 2003-11-23 devnull if(i < 0)
693 6fc7da3c 2006-10-19 devnull goto Err;
694 056fe1ba 2003-11-23 devnull if(i > DEPTH(e.type)){
695 056fe1ba 2003-11-23 devnull if(mode == VtOREAD){
696 d23a617a 2004-03-15 devnull werrstr("bad address 0x%lux", (ulong)bn);
697 056fe1ba 2003-11-23 devnull goto Err;
698 056fe1ba 2003-11-23 devnull }
699 056fe1ba 2003-11-23 devnull index[i] = 0;
700 056fe1ba 2003-11-23 devnull if(growdepth(r, b, &e, i) < 0)
701 056fe1ba 2003-11-23 devnull goto Err;
702 056fe1ba 2003-11-23 devnull }
703 056fe1ba 2003-11-23 devnull
704 056fe1ba 2003-11-23 devnull assert(b->type == VtDirType);
705 056fe1ba 2003-11-23 devnull
706 056fe1ba 2003-11-23 devnull index[DEPTH(e.type)] = r->offset % r->epb;
707 056fe1ba 2003-11-23 devnull
708 056fe1ba 2003-11-23 devnull /* mode for intermediate block */
709 056fe1ba 2003-11-23 devnull m = mode;
710 056fe1ba 2003-11-23 devnull if(m == VtOWRITE)
711 056fe1ba 2003-11-23 devnull m = VtORDWR;
712 056fe1ba 2003-11-23 devnull
713 056fe1ba 2003-11-23 devnull for(i=DEPTH(e.type); i>=0; i--){
714 75d04888 2009-05-25 rsc bb = blockwalk(r, b, index[i], r->c, i==0 ? mode : m, &e);
715 056fe1ba 2003-11-23 devnull if(bb == nil)
716 056fe1ba 2003-11-23 devnull goto Err;
717 056fe1ba 2003-11-23 devnull vtblockput(b);
718 056fe1ba 2003-11-23 devnull b = bb;
719 056fe1ba 2003-11-23 devnull }
720 6fc7da3c 2006-10-19 devnull b->pc = getcallerpc(&r);
721 056fe1ba 2003-11-23 devnull return b;
722 056fe1ba 2003-11-23 devnull Err:
723 056fe1ba 2003-11-23 devnull vtblockput(b);
724 056fe1ba 2003-11-23 devnull return nil;
725 056fe1ba 2003-11-23 devnull }
726 056fe1ba 2003-11-23 devnull
727 056fe1ba 2003-11-23 devnull int
728 d23a617a 2004-03-15 devnull vtfileblockscore(VtFile *r, u32int bn, uchar score[VtScoreSize])
729 056fe1ba 2003-11-23 devnull {
730 056fe1ba 2003-11-23 devnull VtBlock *b, *bb;
731 056fe1ba 2003-11-23 devnull int index[VtPointerDepth+1];
732 056fe1ba 2003-11-23 devnull VtEntry e;
733 056fe1ba 2003-11-23 devnull int i;
734 056fe1ba 2003-11-23 devnull
735 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
736 056fe1ba 2003-11-23 devnull assert(bn != NilBlock);
737 056fe1ba 2003-11-23 devnull
738 056fe1ba 2003-11-23 devnull b = fileload(r, &e);
739 056fe1ba 2003-11-23 devnull if(b == nil)
740 056fe1ba 2003-11-23 devnull return -1;
741 056fe1ba 2003-11-23 devnull
742 e9b70a5f 2008-06-15 rsc if(DEPTH(e.type) == 0){
743 e9b70a5f 2008-06-15 rsc memmove(score, e.score, VtScoreSize);
744 e9b70a5f 2008-06-15 rsc vtblockput(b);
745 e9b70a5f 2008-06-15 rsc return 0;
746 e9b70a5f 2008-06-15 rsc }
747 e9b70a5f 2008-06-15 rsc
748 056fe1ba 2003-11-23 devnull i = mkindices(&e, bn, index);
749 056fe1ba 2003-11-23 devnull if(i < 0){
750 056fe1ba 2003-11-23 devnull vtblockput(b);
751 056fe1ba 2003-11-23 devnull return -1;
752 056fe1ba 2003-11-23 devnull }
753 056fe1ba 2003-11-23 devnull if(i > DEPTH(e.type)){
754 056fe1ba 2003-11-23 devnull memmove(score, vtzeroscore, VtScoreSize);
755 056fe1ba 2003-11-23 devnull vtblockput(b);
756 056fe1ba 2003-11-23 devnull return 0;
757 056fe1ba 2003-11-23 devnull }
758 056fe1ba 2003-11-23 devnull
759 056fe1ba 2003-11-23 devnull index[DEPTH(e.type)] = r->offset % r->epb;
760 056fe1ba 2003-11-23 devnull
761 056fe1ba 2003-11-23 devnull for(i=DEPTH(e.type); i>=1; i--){
762 75d04888 2009-05-25 rsc bb = blockwalk(r, b, index[i], r->c, VtOREAD, &e);
763 056fe1ba 2003-11-23 devnull if(bb == nil)
764 056fe1ba 2003-11-23 devnull goto Err;
765 056fe1ba 2003-11-23 devnull vtblockput(b);
766 056fe1ba 2003-11-23 devnull b = bb;
767 056fe1ba 2003-11-23 devnull if(memcmp(b->score, vtzeroscore, VtScoreSize) == 0)
768 056fe1ba 2003-11-23 devnull break;
769 056fe1ba 2003-11-23 devnull }
770 056fe1ba 2003-11-23 devnull
771 056fe1ba 2003-11-23 devnull memmove(score, b->data+index[0]*VtScoreSize, VtScoreSize);
772 056fe1ba 2003-11-23 devnull vtblockput(b);
773 056fe1ba 2003-11-23 devnull return 0;
774 056fe1ba 2003-11-23 devnull
775 056fe1ba 2003-11-23 devnull Err:
776 056fe1ba 2003-11-23 devnull vtblockput(b);
777 056fe1ba 2003-11-23 devnull return -1;
778 056fe1ba 2003-11-23 devnull }
779 056fe1ba 2003-11-23 devnull
780 056fe1ba 2003-11-23 devnull void
781 056fe1ba 2003-11-23 devnull vtfileincref(VtFile *r)
782 056fe1ba 2003-11-23 devnull {
783 056fe1ba 2003-11-23 devnull qlock(&r->lk);
784 056fe1ba 2003-11-23 devnull r->ref++;
785 056fe1ba 2003-11-23 devnull qunlock(&r->lk);
786 056fe1ba 2003-11-23 devnull }
787 056fe1ba 2003-11-23 devnull
788 056fe1ba 2003-11-23 devnull void
789 056fe1ba 2003-11-23 devnull vtfileclose(VtFile *r)
790 056fe1ba 2003-11-23 devnull {
791 056fe1ba 2003-11-23 devnull if(r == nil)
792 056fe1ba 2003-11-23 devnull return;
793 056fe1ba 2003-11-23 devnull qlock(&r->lk);
794 056fe1ba 2003-11-23 devnull r->ref--;
795 056fe1ba 2003-11-23 devnull if(r->ref){
796 056fe1ba 2003-11-23 devnull qunlock(&r->lk);
797 056fe1ba 2003-11-23 devnull return;
798 056fe1ba 2003-11-23 devnull }
799 056fe1ba 2003-11-23 devnull assert(r->ref == 0);
800 056fe1ba 2003-11-23 devnull qunlock(&r->lk);
801 056fe1ba 2003-11-23 devnull if(r->parent)
802 056fe1ba 2003-11-23 devnull vtfileclose(r->parent);
803 056fe1ba 2003-11-23 devnull memset(r, ~0, sizeof(*r));
804 056fe1ba 2003-11-23 devnull vtfree(r);
805 056fe1ba 2003-11-23 devnull }
806 056fe1ba 2003-11-23 devnull
807 056fe1ba 2003-11-23 devnull /*
808 056fe1ba 2003-11-23 devnull * Retrieve the block containing the entry for r.
809 056fe1ba 2003-11-23 devnull * If a snapshot has happened, we might need
810 056fe1ba 2003-11-23 devnull * to get a new copy of the block. We avoid this
811 056fe1ba 2003-11-23 devnull * in the common case by caching the score for
812 056fe1ba 2003-11-23 devnull * the block and the last epoch in which it was valid.
813 056fe1ba 2003-11-23 devnull *
814 056fe1ba 2003-11-23 devnull * We use r->mode to tell the difference between active
815 056fe1ba 2003-11-23 devnull * file system VtFiles (VtORDWR) and VtFiles for the
816 056fe1ba 2003-11-23 devnull * snapshot file system (VtOREAD).
817 056fe1ba 2003-11-23 devnull */
818 056fe1ba 2003-11-23 devnull static VtBlock*
819 056fe1ba 2003-11-23 devnull fileloadblock(VtFile *r, int mode)
820 056fe1ba 2003-11-23 devnull {
821 056fe1ba 2003-11-23 devnull char e[ERRMAX];
822 056fe1ba 2003-11-23 devnull u32int addr;
823 056fe1ba 2003-11-23 devnull VtBlock *b;
824 056fe1ba 2003-11-23 devnull
825 056fe1ba 2003-11-23 devnull switch(r->mode){
826 056fe1ba 2003-11-23 devnull default:
827 056fe1ba 2003-11-23 devnull assert(0);
828 056fe1ba 2003-11-23 devnull case VtORDWR:
829 056fe1ba 2003-11-23 devnull assert(r->mode == VtORDWR);
830 056fe1ba 2003-11-23 devnull if(r->local == 1){
831 75d04888 2009-05-25 rsc b = vtcacheglobal(r->c, r->score, VtDirType, r->bsize);
832 056fe1ba 2003-11-23 devnull if(b == nil)
833 056fe1ba 2003-11-23 devnull return nil;
834 6fc7da3c 2006-10-19 devnull b->pc = getcallerpc(&r);
835 056fe1ba 2003-11-23 devnull return b;
836 056fe1ba 2003-11-23 devnull }
837 056fe1ba 2003-11-23 devnull assert(r->parent != nil);
838 056fe1ba 2003-11-23 devnull if(vtfilelock(r->parent, VtORDWR) < 0)
839 056fe1ba 2003-11-23 devnull return nil;
840 056fe1ba 2003-11-23 devnull b = vtfileblock(r->parent, r->offset/r->epb, VtORDWR);
841 056fe1ba 2003-11-23 devnull vtfileunlock(r->parent);
842 056fe1ba 2003-11-23 devnull if(b == nil)
843 056fe1ba 2003-11-23 devnull return nil;
844 056fe1ba 2003-11-23 devnull memmove(r->score, b->score, VtScoreSize);
845 056fe1ba 2003-11-23 devnull r->local = 1;
846 056fe1ba 2003-11-23 devnull return b;
847 056fe1ba 2003-11-23 devnull
848 056fe1ba 2003-11-23 devnull case VtOREAD:
849 056fe1ba 2003-11-23 devnull if(mode == VtORDWR){
850 056fe1ba 2003-11-23 devnull werrstr("read/write lock of read-only file");
851 056fe1ba 2003-11-23 devnull return nil;
852 056fe1ba 2003-11-23 devnull }
853 056fe1ba 2003-11-23 devnull addr = vtglobaltolocal(r->score);
854 056fe1ba 2003-11-23 devnull if(addr == NilBlock)
855 75d04888 2009-05-25 rsc return vtcacheglobal(r->c, r->score, VtDirType, r->bsize);
856 056fe1ba 2003-11-23 devnull
857 056fe1ba 2003-11-23 devnull b = vtcachelocal(r->c, addr, VtDirType);
858 056fe1ba 2003-11-23 devnull if(b)
859 056fe1ba 2003-11-23 devnull return b;
860 056fe1ba 2003-11-23 devnull
861 056fe1ba 2003-11-23 devnull /*
862 056fe1ba 2003-11-23 devnull * If it failed because the epochs don't match, the block has been
863 056fe1ba 2003-11-23 devnull * archived and reclaimed. Rewalk from the parent and get the
864 056fe1ba 2003-11-23 devnull * new pointer. This can't happen in the VtORDWR case
865 056fe1ba 2003-11-23 devnull * above because blocks in the current epoch don't get
866 056fe1ba 2003-11-23 devnull * reclaimed. The fact that we're VtOREAD means we're
867 056fe1ba 2003-11-23 devnull * a snapshot. (Or else the file system is read-only, but then
868 056fe1ba 2003-11-23 devnull * the archiver isn't going around deleting blocks.)
869 056fe1ba 2003-11-23 devnull */
870 056fe1ba 2003-11-23 devnull rerrstr(e, sizeof e);
871 056fe1ba 2003-11-23 devnull if(strcmp(e, ELabelMismatch) == 0){
872 056fe1ba 2003-11-23 devnull if(vtfilelock(r->parent, VtOREAD) < 0)
873 056fe1ba 2003-11-23 devnull return nil;
874 056fe1ba 2003-11-23 devnull b = vtfileblock(r->parent, r->offset/r->epb, VtOREAD);
875 056fe1ba 2003-11-23 devnull vtfileunlock(r->parent);
876 056fe1ba 2003-11-23 devnull if(b){
877 056fe1ba 2003-11-23 devnull fprint(2, "vtfilealloc: lost %V found %V\n",
878 056fe1ba 2003-11-23 devnull r->score, b->score);
879 056fe1ba 2003-11-23 devnull memmove(r->score, b->score, VtScoreSize);
880 056fe1ba 2003-11-23 devnull return b;
881 056fe1ba 2003-11-23 devnull }
882 056fe1ba 2003-11-23 devnull }
883 056fe1ba 2003-11-23 devnull return nil;
884 056fe1ba 2003-11-23 devnull }
885 056fe1ba 2003-11-23 devnull }
886 056fe1ba 2003-11-23 devnull
887 056fe1ba 2003-11-23 devnull int
888 056fe1ba 2003-11-23 devnull vtfilelock(VtFile *r, int mode)
889 056fe1ba 2003-11-23 devnull {
890 056fe1ba 2003-11-23 devnull VtBlock *b;
891 056fe1ba 2003-11-23 devnull
892 056fe1ba 2003-11-23 devnull if(mode == -1)
893 056fe1ba 2003-11-23 devnull mode = r->mode;
894 056fe1ba 2003-11-23 devnull
895 056fe1ba 2003-11-23 devnull b = fileloadblock(r, mode);
896 056fe1ba 2003-11-23 devnull if(b == nil)
897 056fe1ba 2003-11-23 devnull return -1;
898 056fe1ba 2003-11-23 devnull /*
899 056fe1ba 2003-11-23 devnull * The fact that we are holding b serves as the
900 056fe1ba 2003-11-23 devnull * lock entitling us to write to r->b.
901 056fe1ba 2003-11-23 devnull */
902 056fe1ba 2003-11-23 devnull assert(r->b == nil);
903 056fe1ba 2003-11-23 devnull r->b = b;
904 6fc7da3c 2006-10-19 devnull b->pc = getcallerpc(&r);
905 056fe1ba 2003-11-23 devnull return 0;
906 056fe1ba 2003-11-23 devnull }
907 056fe1ba 2003-11-23 devnull
908 056fe1ba 2003-11-23 devnull /*
909 056fe1ba 2003-11-23 devnull * Lock two (usually sibling) VtFiles. This needs special care
910 056fe1ba 2003-11-23 devnull * because the Entries for both vtFiles might be in the same block.
911 056fe1ba 2003-11-23 devnull * We also try to lock blocks in left-to-right order within the tree.
912 056fe1ba 2003-11-23 devnull */
913 056fe1ba 2003-11-23 devnull int
914 056fe1ba 2003-11-23 devnull vtfilelock2(VtFile *r, VtFile *rr, int mode)
915 056fe1ba 2003-11-23 devnull {
916 056fe1ba 2003-11-23 devnull VtBlock *b, *bb;
917 056fe1ba 2003-11-23 devnull
918 056fe1ba 2003-11-23 devnull if(rr == nil)
919 056fe1ba 2003-11-23 devnull return vtfilelock(r, mode);
920 056fe1ba 2003-11-23 devnull
921 056fe1ba 2003-11-23 devnull if(mode == -1)
922 056fe1ba 2003-11-23 devnull mode = r->mode;
923 056fe1ba 2003-11-23 devnull
924 056fe1ba 2003-11-23 devnull if(r->parent==rr->parent && r->offset/r->epb == rr->offset/rr->epb){
925 056fe1ba 2003-11-23 devnull b = fileloadblock(r, mode);
926 056fe1ba 2003-11-23 devnull if(b == nil)
927 056fe1ba 2003-11-23 devnull return -1;
928 056fe1ba 2003-11-23 devnull vtblockduplock(b);
929 056fe1ba 2003-11-23 devnull bb = b;
930 056fe1ba 2003-11-23 devnull }else if(r->parent==rr->parent || r->offset > rr->offset){
931 056fe1ba 2003-11-23 devnull bb = fileloadblock(rr, mode);
932 056fe1ba 2003-11-23 devnull b = fileloadblock(r, mode);
933 056fe1ba 2003-11-23 devnull }else{
934 056fe1ba 2003-11-23 devnull b = fileloadblock(r, mode);
935 056fe1ba 2003-11-23 devnull bb = fileloadblock(rr, mode);
936 056fe1ba 2003-11-23 devnull }
937 056fe1ba 2003-11-23 devnull if(b == nil || bb == nil){
938 056fe1ba 2003-11-23 devnull if(b)
939 056fe1ba 2003-11-23 devnull vtblockput(b);
940 056fe1ba 2003-11-23 devnull if(bb)
941 056fe1ba 2003-11-23 devnull vtblockput(bb);
942 056fe1ba 2003-11-23 devnull return -1;
943 056fe1ba 2003-11-23 devnull }
944 056fe1ba 2003-11-23 devnull
945 056fe1ba 2003-11-23 devnull /*
946 056fe1ba 2003-11-23 devnull * The fact that we are holding b and bb serves
947 056fe1ba 2003-11-23 devnull * as the lock entitling us to write to r->b and rr->b.
948 056fe1ba 2003-11-23 devnull */
949 056fe1ba 2003-11-23 devnull r->b = b;
950 056fe1ba 2003-11-23 devnull rr->b = bb;
951 6fc7da3c 2006-10-19 devnull b->pc = getcallerpc(&r);
952 6fc7da3c 2006-10-19 devnull bb->pc = getcallerpc(&r);
953 056fe1ba 2003-11-23 devnull return 0;
954 056fe1ba 2003-11-23 devnull }
955 056fe1ba 2003-11-23 devnull
956 056fe1ba 2003-11-23 devnull void
957 056fe1ba 2003-11-23 devnull vtfileunlock(VtFile *r)
958 056fe1ba 2003-11-23 devnull {
959 056fe1ba 2003-11-23 devnull VtBlock *b;
960 056fe1ba 2003-11-23 devnull
961 056fe1ba 2003-11-23 devnull if(r->b == nil){
962 056fe1ba 2003-11-23 devnull fprint(2, "vtfileunlock: already unlocked\n");
963 056fe1ba 2003-11-23 devnull abort();
964 056fe1ba 2003-11-23 devnull }
965 056fe1ba 2003-11-23 devnull b = r->b;
966 056fe1ba 2003-11-23 devnull r->b = nil;
967 056fe1ba 2003-11-23 devnull vtblockput(b);
968 056fe1ba 2003-11-23 devnull }
969 056fe1ba 2003-11-23 devnull
970 056fe1ba 2003-11-23 devnull static VtBlock*
971 056fe1ba 2003-11-23 devnull fileload(VtFile *r, VtEntry *e)
972 056fe1ba 2003-11-23 devnull {
973 056fe1ba 2003-11-23 devnull VtBlock *b;
974 056fe1ba 2003-11-23 devnull
975 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
976 056fe1ba 2003-11-23 devnull b = r->b;
977 056fe1ba 2003-11-23 devnull if(vtentryunpack(e, b->data, r->offset % r->epb) < 0)
978 056fe1ba 2003-11-23 devnull return nil;
979 056fe1ba 2003-11-23 devnull vtblockduplock(b);
980 056fe1ba 2003-11-23 devnull return b;
981 056fe1ba 2003-11-23 devnull }
982 056fe1ba 2003-11-23 devnull
983 056fe1ba 2003-11-23 devnull static int
984 056fe1ba 2003-11-23 devnull sizetodepth(uvlong s, int psize, int dsize)
985 056fe1ba 2003-11-23 devnull {
986 056fe1ba 2003-11-23 devnull int np;
987 056fe1ba 2003-11-23 devnull int d;
988 fa325e9b 2020-01-10 cross
989 056fe1ba 2003-11-23 devnull /* determine pointer depth */
990 056fe1ba 2003-11-23 devnull np = psize/VtScoreSize;
991 056fe1ba 2003-11-23 devnull s = (s + dsize - 1)/dsize;
992 056fe1ba 2003-11-23 devnull for(d = 0; s > 1; d++)
993 056fe1ba 2003-11-23 devnull s = (s + np - 1)/np;
994 056fe1ba 2003-11-23 devnull return d;
995 056fe1ba 2003-11-23 devnull }
996 056fe1ba 2003-11-23 devnull
997 056fe1ba 2003-11-23 devnull long
998 056fe1ba 2003-11-23 devnull vtfileread(VtFile *f, void *data, long count, vlong offset)
999 056fe1ba 2003-11-23 devnull {
1000 056fe1ba 2003-11-23 devnull int frag;
1001 056fe1ba 2003-11-23 devnull VtBlock *b;
1002 056fe1ba 2003-11-23 devnull VtEntry e;
1003 056fe1ba 2003-11-23 devnull
1004 056fe1ba 2003-11-23 devnull assert(ISLOCKED(f));
1005 056fe1ba 2003-11-23 devnull
1006 056fe1ba 2003-11-23 devnull vtfilegetentry(f, &e);
1007 056fe1ba 2003-11-23 devnull if(count == 0)
1008 056fe1ba 2003-11-23 devnull return 0;
1009 056fe1ba 2003-11-23 devnull if(count < 0 || offset < 0){
1010 056fe1ba 2003-11-23 devnull werrstr("vtfileread: bad offset or count");
1011 056fe1ba 2003-11-23 devnull return -1;
1012 056fe1ba 2003-11-23 devnull }
1013 056fe1ba 2003-11-23 devnull if(offset >= e.size)
1014 056fe1ba 2003-11-23 devnull return 0;
1015 056fe1ba 2003-11-23 devnull
1016 056fe1ba 2003-11-23 devnull if(offset+count > e.size)
1017 056fe1ba 2003-11-23 devnull count = e.size - offset;
1018 056fe1ba 2003-11-23 devnull
1019 056fe1ba 2003-11-23 devnull frag = offset % e.dsize;
1020 056fe1ba 2003-11-23 devnull if(frag+count > e.dsize)
1021 056fe1ba 2003-11-23 devnull count = e.dsize - frag;
1022 056fe1ba 2003-11-23 devnull
1023 056fe1ba 2003-11-23 devnull b = vtfileblock(f, offset/e.dsize, VtOREAD);
1024 056fe1ba 2003-11-23 devnull if(b == nil)
1025 056fe1ba 2003-11-23 devnull return -1;
1026 056fe1ba 2003-11-23 devnull
1027 056fe1ba 2003-11-23 devnull memmove(data, b->data+frag, count);
1028 056fe1ba 2003-11-23 devnull vtblockput(b);
1029 056fe1ba 2003-11-23 devnull return count;
1030 056fe1ba 2003-11-23 devnull }
1031 056fe1ba 2003-11-23 devnull
1032 056fe1ba 2003-11-23 devnull static long
1033 056fe1ba 2003-11-23 devnull filewrite1(VtFile *f, void *data, long count, vlong offset)
1034 056fe1ba 2003-11-23 devnull {
1035 056fe1ba 2003-11-23 devnull int frag, m;
1036 056fe1ba 2003-11-23 devnull VtBlock *b;
1037 056fe1ba 2003-11-23 devnull VtEntry e;
1038 056fe1ba 2003-11-23 devnull
1039 056fe1ba 2003-11-23 devnull vtfilegetentry(f, &e);
1040 056fe1ba 2003-11-23 devnull if(count < 0 || offset < 0){
1041 6ce75e8d 2007-04-21 devnull werrstr("vtfilewrite: bad offset or count");
1042 056fe1ba 2003-11-23 devnull return -1;
1043 056fe1ba 2003-11-23 devnull }
1044 056fe1ba 2003-11-23 devnull
1045 056fe1ba 2003-11-23 devnull frag = offset % e.dsize;
1046 056fe1ba 2003-11-23 devnull if(frag+count > e.dsize)
1047 056fe1ba 2003-11-23 devnull count = e.dsize - frag;
1048 056fe1ba 2003-11-23 devnull
1049 056fe1ba 2003-11-23 devnull m = VtORDWR;
1050 056fe1ba 2003-11-23 devnull if(frag == 0 && count == e.dsize)
1051 056fe1ba 2003-11-23 devnull m = VtOWRITE;
1052 056fe1ba 2003-11-23 devnull
1053 056fe1ba 2003-11-23 devnull b = vtfileblock(f, offset/e.dsize, m);
1054 056fe1ba 2003-11-23 devnull if(b == nil)
1055 056fe1ba 2003-11-23 devnull return -1;
1056 056fe1ba 2003-11-23 devnull
1057 056fe1ba 2003-11-23 devnull memmove(b->data+frag, data, count);
1058 e9b70a5f 2008-06-15 rsc if(m == VtOWRITE && frag+count < e.dsize)
1059 e9b70a5f 2008-06-15 rsc memset(b->data+frag+count, 0, e.dsize-frag-count);
1060 056fe1ba 2003-11-23 devnull
1061 056fe1ba 2003-11-23 devnull if(offset+count > e.size){
1062 056fe1ba 2003-11-23 devnull vtfilegetentry(f, &e);
1063 056fe1ba 2003-11-23 devnull e.size = offset+count;
1064 056fe1ba 2003-11-23 devnull vtfilesetentry(f, &e);
1065 056fe1ba 2003-11-23 devnull }
1066 056fe1ba 2003-11-23 devnull
1067 056fe1ba 2003-11-23 devnull vtblockput(b);
1068 056fe1ba 2003-11-23 devnull return count;
1069 056fe1ba 2003-11-23 devnull }
1070 056fe1ba 2003-11-23 devnull
1071 056fe1ba 2003-11-23 devnull long
1072 056fe1ba 2003-11-23 devnull vtfilewrite(VtFile *f, void *data, long count, vlong offset)
1073 056fe1ba 2003-11-23 devnull {
1074 056fe1ba 2003-11-23 devnull long tot, m;
1075 056fe1ba 2003-11-23 devnull
1076 056fe1ba 2003-11-23 devnull assert(ISLOCKED(f));
1077 056fe1ba 2003-11-23 devnull
1078 056fe1ba 2003-11-23 devnull tot = 0;
1079 056fe1ba 2003-11-23 devnull m = 0;
1080 056fe1ba 2003-11-23 devnull while(tot < count){
1081 056fe1ba 2003-11-23 devnull m = filewrite1(f, (char*)data+tot, count-tot, offset+tot);
1082 056fe1ba 2003-11-23 devnull if(m <= 0)
1083 056fe1ba 2003-11-23 devnull break;
1084 056fe1ba 2003-11-23 devnull tot += m;
1085 056fe1ba 2003-11-23 devnull }
1086 056fe1ba 2003-11-23 devnull if(tot==0)
1087 056fe1ba 2003-11-23 devnull return m;
1088 056fe1ba 2003-11-23 devnull return tot;
1089 056fe1ba 2003-11-23 devnull }
1090 056fe1ba 2003-11-23 devnull
1091 056fe1ba 2003-11-23 devnull static int
1092 056fe1ba 2003-11-23 devnull flushblock(VtCache *c, VtBlock *bb, uchar score[VtScoreSize], int ppb, int epb,
1093 056fe1ba 2003-11-23 devnull int type)
1094 056fe1ba 2003-11-23 devnull {
1095 056fe1ba 2003-11-23 devnull u32int addr;
1096 056fe1ba 2003-11-23 devnull VtBlock *b;
1097 056fe1ba 2003-11-23 devnull VtEntry e;
1098 056fe1ba 2003-11-23 devnull int i;
1099 056fe1ba 2003-11-23 devnull
1100 056fe1ba 2003-11-23 devnull addr = vtglobaltolocal(score);
1101 056fe1ba 2003-11-23 devnull if(addr == NilBlock)
1102 056fe1ba 2003-11-23 devnull return 0;
1103 056fe1ba 2003-11-23 devnull
1104 056fe1ba 2003-11-23 devnull if(bb){
1105 056fe1ba 2003-11-23 devnull b = bb;
1106 056fe1ba 2003-11-23 devnull if(memcmp(b->score, score, VtScoreSize) != 0)
1107 056fe1ba 2003-11-23 devnull abort();
1108 056fe1ba 2003-11-23 devnull }else
1109 056fe1ba 2003-11-23 devnull if((b = vtcachelocal(c, addr, type)) == nil)
1110 056fe1ba 2003-11-23 devnull return -1;
1111 056fe1ba 2003-11-23 devnull
1112 056fe1ba 2003-11-23 devnull switch(type){
1113 056fe1ba 2003-11-23 devnull case VtDataType:
1114 056fe1ba 2003-11-23 devnull break;
1115 056fe1ba 2003-11-23 devnull
1116 056fe1ba 2003-11-23 devnull case VtDirType:
1117 056fe1ba 2003-11-23 devnull for(i=0; i<epb; i++){
1118 056fe1ba 2003-11-23 devnull if(vtentryunpack(&e, b->data, i) < 0)
1119 056fe1ba 2003-11-23 devnull goto Err;
1120 e9b70a5f 2008-06-15 rsc if(!(e.flags&VtEntryActive))
1121 e9b70a5f 2008-06-15 rsc continue;
1122 056fe1ba 2003-11-23 devnull if(flushblock(c, nil, e.score, e.psize/VtScoreSize, e.dsize/VtEntrySize,
1123 056fe1ba 2003-11-23 devnull e.type) < 0)
1124 056fe1ba 2003-11-23 devnull goto Err;
1125 e9b70a5f 2008-06-15 rsc vtentrypack(&e, b->data, i);
1126 056fe1ba 2003-11-23 devnull }
1127 056fe1ba 2003-11-23 devnull break;
1128 fa325e9b 2020-01-10 cross
1129 056fe1ba 2003-11-23 devnull default: /* VtPointerTypeX */
1130 056fe1ba 2003-11-23 devnull for(i=0; i<ppb; i++){
1131 056fe1ba 2003-11-23 devnull if(flushblock(c, nil, b->data+VtScoreSize*i, ppb, epb, type-1) < 0)
1132 056fe1ba 2003-11-23 devnull goto Err;
1133 056fe1ba 2003-11-23 devnull }
1134 056fe1ba 2003-11-23 devnull break;
1135 056fe1ba 2003-11-23 devnull }
1136 056fe1ba 2003-11-23 devnull
1137 056fe1ba 2003-11-23 devnull if(vtblockwrite(b) < 0)
1138 056fe1ba 2003-11-23 devnull goto Err;
1139 056fe1ba 2003-11-23 devnull memmove(score, b->score, VtScoreSize);
1140 056fe1ba 2003-11-23 devnull if(b != bb)
1141 056fe1ba 2003-11-23 devnull vtblockput(b);
1142 056fe1ba 2003-11-23 devnull return 0;
1143 056fe1ba 2003-11-23 devnull
1144 056fe1ba 2003-11-23 devnull Err:
1145 056fe1ba 2003-11-23 devnull if(b != bb)
1146 056fe1ba 2003-11-23 devnull vtblockput(b);
1147 056fe1ba 2003-11-23 devnull return -1;
1148 056fe1ba 2003-11-23 devnull }
1149 056fe1ba 2003-11-23 devnull
1150 056fe1ba 2003-11-23 devnull int
1151 056fe1ba 2003-11-23 devnull vtfileflush(VtFile *f)
1152 056fe1ba 2003-11-23 devnull {
1153 056fe1ba 2003-11-23 devnull int ret;
1154 056fe1ba 2003-11-23 devnull VtBlock *b;
1155 056fe1ba 2003-11-23 devnull VtEntry e;
1156 056fe1ba 2003-11-23 devnull
1157 056fe1ba 2003-11-23 devnull assert(ISLOCKED(f));
1158 056fe1ba 2003-11-23 devnull b = fileload(f, &e);
1159 056fe1ba 2003-11-23 devnull if(!(e.flags&VtEntryLocal)){
1160 056fe1ba 2003-11-23 devnull vtblockput(b);
1161 056fe1ba 2003-11-23 devnull return 0;
1162 056fe1ba 2003-11-23 devnull }
1163 056fe1ba 2003-11-23 devnull
1164 056fe1ba 2003-11-23 devnull ret = flushblock(f->c, nil, e.score, e.psize/VtScoreSize, e.dsize/VtEntrySize,
1165 056fe1ba 2003-11-23 devnull e.type);
1166 7cb74894 2004-06-17 devnull if(ret < 0){
1167 056fe1ba 2003-11-23 devnull vtblockput(b);
1168 056fe1ba 2003-11-23 devnull return -1;
1169 056fe1ba 2003-11-23 devnull }
1170 056fe1ba 2003-11-23 devnull
1171 056fe1ba 2003-11-23 devnull vtentrypack(&e, b->data, f->offset % f->epb);
1172 056fe1ba 2003-11-23 devnull vtblockput(b);
1173 056fe1ba 2003-11-23 devnull return 0;
1174 056fe1ba 2003-11-23 devnull }
1175 056fe1ba 2003-11-23 devnull
1176 056fe1ba 2003-11-23 devnull int
1177 056fe1ba 2003-11-23 devnull vtfileflushbefore(VtFile *r, u64int offset)
1178 056fe1ba 2003-11-23 devnull {
1179 056fe1ba 2003-11-23 devnull VtBlock *b, *bb;
1180 056fe1ba 2003-11-23 devnull VtEntry e;
1181 59a96820 2004-06-17 devnull int i, base, depth, ppb, epb, doflush;
1182 59a96820 2004-06-17 devnull int index[VtPointerDepth+1], j, ret;
1183 056fe1ba 2003-11-23 devnull VtBlock *bi[VtPointerDepth+2];
1184 056fe1ba 2003-11-23 devnull uchar *score;
1185 056fe1ba 2003-11-23 devnull
1186 056fe1ba 2003-11-23 devnull assert(ISLOCKED(r));
1187 056fe1ba 2003-11-23 devnull if(offset == 0)
1188 056fe1ba 2003-11-23 devnull return 0;
1189 056fe1ba 2003-11-23 devnull
1190 056fe1ba 2003-11-23 devnull b = fileload(r, &e);
1191 056fe1ba 2003-11-23 devnull if(b == nil)
1192 056fe1ba 2003-11-23 devnull return -1;
1193 056fe1ba 2003-11-23 devnull
1194 59a96820 2004-06-17 devnull /*
1195 59a96820 2004-06-17 devnull * compute path through tree for the last written byte and the next one.
1196 59a96820 2004-06-17 devnull */
1197 056fe1ba 2003-11-23 devnull ret = -1;
1198 056fe1ba 2003-11-23 devnull memset(bi, 0, sizeof bi);
1199 056fe1ba 2003-11-23 devnull depth = DEPTH(e.type);
1200 056fe1ba 2003-11-23 devnull bi[depth+1] = b;
1201 056fe1ba 2003-11-23 devnull i = mkindices(&e, (offset-1)/e.dsize, index);
1202 056fe1ba 2003-11-23 devnull if(i < 0)
1203 056fe1ba 2003-11-23 devnull goto Err;
1204 056fe1ba 2003-11-23 devnull if(i > depth)
1205 056fe1ba 2003-11-23 devnull goto Err;
1206 056fe1ba 2003-11-23 devnull ppb = e.psize / VtScoreSize;
1207 056fe1ba 2003-11-23 devnull epb = e.dsize / VtEntrySize;
1208 056fe1ba 2003-11-23 devnull
1209 59a96820 2004-06-17 devnull /*
1210 59a96820 2004-06-17 devnull * load the blocks along the last written byte
1211 59a96820 2004-06-17 devnull */
1212 056fe1ba 2003-11-23 devnull index[depth] = r->offset % r->epb;
1213 056fe1ba 2003-11-23 devnull for(i=depth; i>=0; i--){
1214 75d04888 2009-05-25 rsc bb = blockwalk(r, b, index[i], r->c, VtORDWR, &e);
1215 056fe1ba 2003-11-23 devnull if(bb == nil)
1216 056fe1ba 2003-11-23 devnull goto Err;
1217 056fe1ba 2003-11-23 devnull bi[i] = bb;
1218 056fe1ba 2003-11-23 devnull b = bb;
1219 056fe1ba 2003-11-23 devnull }
1220 056fe1ba 2003-11-23 devnull ret = 0;
1221 056fe1ba 2003-11-23 devnull
1222 59a96820 2004-06-17 devnull /*
1223 59a96820 2004-06-17 devnull * walk up the path from leaf to root, flushing anything that
1224 59a96820 2004-06-17 devnull * has been finished.
1225 59a96820 2004-06-17 devnull */
1226 056fe1ba 2003-11-23 devnull base = e.type&~VtTypeDepthMask;
1227 005ee04b 2004-06-17 devnull for(i=0; i<=depth; i++){
1228 59a96820 2004-06-17 devnull doflush = 0;
1229 056fe1ba 2003-11-23 devnull if(i == 0){
1230 59a96820 2004-06-17 devnull /* leaf: data or dir block */
1231 59a96820 2004-06-17 devnull if(offset%e.dsize == 0)
1232 59a96820 2004-06-17 devnull doflush = 1;
1233 056fe1ba 2003-11-23 devnull }else{
1234 59a96820 2004-06-17 devnull /*
1235 59a96820 2004-06-17 devnull * interior node: pointer blocks.
1236 fa325e9b 2020-01-10 cross * specifically, b = bi[i] is a block whose index[i-1]'th entry
1237 fa325e9b 2020-01-10 cross * points at bi[i-1].
1238 59a96820 2004-06-17 devnull */
1239 056fe1ba 2003-11-23 devnull b = bi[i];
1240 59a96820 2004-06-17 devnull
1241 056fe1ba 2003-11-23 devnull /*
1242 fa325e9b 2020-01-10 cross * the index entries up to but not including index[i-1] point at
1243 59a96820 2004-06-17 devnull * finished blocks, so flush them for sure.
1244 056fe1ba 2003-11-23 devnull */
1245 056fe1ba 2003-11-23 devnull for(j=0; j<index[i-1]; j++)
1246 056fe1ba 2003-11-23 devnull if(flushblock(r->c, nil, b->data+j*VtScoreSize, ppb, epb, base+i-1) < 0)
1247 056fe1ba 2003-11-23 devnull goto Err;
1248 59a96820 2004-06-17 devnull
1249 056fe1ba 2003-11-23 devnull /*
1250 59a96820 2004-06-17 devnull * if index[i-1] is the last entry in the block and is global
1251 59a96820 2004-06-17 devnull * (i.e. the kid is flushed), then we can flush this block.
1252 056fe1ba 2003-11-23 devnull */
1253 59a96820 2004-06-17 devnull if(j==ppb-1 && vtglobaltolocal(b->data+j*VtScoreSize)==NilBlock)
1254 59a96820 2004-06-17 devnull doflush = 1;
1255 056fe1ba 2003-11-23 devnull }
1256 59a96820 2004-06-17 devnull if(doflush){
1257 056fe1ba 2003-11-23 devnull if(i == depth)
1258 056fe1ba 2003-11-23 devnull score = e.score;
1259 056fe1ba 2003-11-23 devnull else
1260 056fe1ba 2003-11-23 devnull score = bi[i+1]->data+index[i]*VtScoreSize;
1261 056fe1ba 2003-11-23 devnull if(flushblock(r->c, bi[i], score, ppb, epb, base+i) < 0)
1262 056fe1ba 2003-11-23 devnull goto Err;
1263 056fe1ba 2003-11-23 devnull }
1264 056fe1ba 2003-11-23 devnull }
1265 056fe1ba 2003-11-23 devnull
1266 056fe1ba 2003-11-23 devnull Err:
1267 056fe1ba 2003-11-23 devnull /* top: entry. do this always so that the score is up-to-date */
1268 056fe1ba 2003-11-23 devnull vtentrypack(&e, bi[depth+1]->data, index[depth]);
1269 056fe1ba 2003-11-23 devnull for(i=0; i<nelem(bi); i++)
1270 056fe1ba 2003-11-23 devnull if(bi[i])
1271 056fe1ba 2003-11-23 devnull vtblockput(bi[i]);
1272 056fe1ba 2003-11-23 devnull return ret;
1273 056fe1ba 2003-11-23 devnull }