Blame


1 7a4ee46d 2003-11-23 devnull #include "stdinc.h"
2 7a4ee46d 2003-11-23 devnull #include "dat.h"
3 7a4ee46d 2003-11-23 devnull #include "fns.h"
4 7a4ee46d 2003-11-23 devnull
5 7a4ee46d 2003-11-23 devnull typedef struct ASum ASum;
6 7a4ee46d 2003-11-23 devnull
7 7a4ee46d 2003-11-23 devnull struct ASum
8 7a4ee46d 2003-11-23 devnull {
9 7a4ee46d 2003-11-23 devnull Arena *arena;
10 7a4ee46d 2003-11-23 devnull ASum *next;
11 7a4ee46d 2003-11-23 devnull };
12 7a4ee46d 2003-11-23 devnull
13 7a4ee46d 2003-11-23 devnull static void sealarena(Arena *arena);
14 7a4ee46d 2003-11-23 devnull static int okarena(Arena *arena);
15 7a4ee46d 2003-11-23 devnull static int loadarena(Arena *arena);
16 7a4ee46d 2003-11-23 devnull static CIBlock *getcib(Arena *arena, int clump, int writing, CIBlock *rock);
17 7a4ee46d 2003-11-23 devnull static void putcib(Arena *arena, CIBlock *cib);
18 7a4ee46d 2003-11-23 devnull static void sumproc(void *);
19 7a4ee46d 2003-11-23 devnull
20 7a4ee46d 2003-11-23 devnull static QLock sumlock;
21 7a4ee46d 2003-11-23 devnull static Rendez sumwait;
22 7a4ee46d 2003-11-23 devnull static ASum *sumq;
23 7a4ee46d 2003-11-23 devnull
24 7a4ee46d 2003-11-23 devnull int
25 7a4ee46d 2003-11-23 devnull initarenasum(void)
26 7a4ee46d 2003-11-23 devnull {
27 7a4ee46d 2003-11-23 devnull sumwait.l = &sumlock;
28 7a4ee46d 2003-11-23 devnull
29 7a4ee46d 2003-11-23 devnull if(vtproc(sumproc, nil) < 0){
30 7a4ee46d 2003-11-23 devnull seterr(EOk, "can't start arena checksum slave: %r");
31 7a4ee46d 2003-11-23 devnull return -1;
32 7a4ee46d 2003-11-23 devnull }
33 7a4ee46d 2003-11-23 devnull return 0;
34 7a4ee46d 2003-11-23 devnull }
35 7a4ee46d 2003-11-23 devnull
36 7a4ee46d 2003-11-23 devnull /*
37 7a4ee46d 2003-11-23 devnull * make an Arena, and initialize it based upon the disk header and trailer.
38 7a4ee46d 2003-11-23 devnull */
39 7a4ee46d 2003-11-23 devnull Arena*
40 7a4ee46d 2003-11-23 devnull initarena(Part *part, u64int base, u64int size, u32int blocksize)
41 7a4ee46d 2003-11-23 devnull {
42 7a4ee46d 2003-11-23 devnull Arena *arena;
43 7a4ee46d 2003-11-23 devnull
44 7a4ee46d 2003-11-23 devnull arena = MKZ(Arena);
45 7a4ee46d 2003-11-23 devnull arena->part = part;
46 7a4ee46d 2003-11-23 devnull arena->blocksize = blocksize;
47 7a4ee46d 2003-11-23 devnull arena->clumpmax = arena->blocksize / ClumpInfoSize;
48 7a4ee46d 2003-11-23 devnull arena->base = base + blocksize;
49 7a4ee46d 2003-11-23 devnull arena->size = size - 2 * blocksize;
50 7a4ee46d 2003-11-23 devnull
51 7a4ee46d 2003-11-23 devnull if(loadarena(arena) < 0){
52 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "arena header or trailer corrupted");
53 7a4ee46d 2003-11-23 devnull freearena(arena);
54 7a4ee46d 2003-11-23 devnull return nil;
55 7a4ee46d 2003-11-23 devnull }
56 7a4ee46d 2003-11-23 devnull if(okarena(arena) < 0){
57 7a4ee46d 2003-11-23 devnull freearena(arena);
58 7a4ee46d 2003-11-23 devnull return nil;
59 7a4ee46d 2003-11-23 devnull }
60 7a4ee46d 2003-11-23 devnull
61 7a4ee46d 2003-11-23 devnull if(arena->sealed && scorecmp(zeroscore, arena->score)==0)
62 7a4ee46d 2003-11-23 devnull backsumarena(arena);
63 7a4ee46d 2003-11-23 devnull
64 7a4ee46d 2003-11-23 devnull return arena;
65 7a4ee46d 2003-11-23 devnull }
66 7a4ee46d 2003-11-23 devnull
67 7a4ee46d 2003-11-23 devnull void
68 7a4ee46d 2003-11-23 devnull freearena(Arena *arena)
69 7a4ee46d 2003-11-23 devnull {
70 7a4ee46d 2003-11-23 devnull if(arena == nil)
71 7a4ee46d 2003-11-23 devnull return;
72 7a4ee46d 2003-11-23 devnull if(arena->cib.data != nil){
73 7a4ee46d 2003-11-23 devnull putdblock(arena->cib.data);
74 7a4ee46d 2003-11-23 devnull arena->cib.data = nil;
75 7a4ee46d 2003-11-23 devnull }
76 7a4ee46d 2003-11-23 devnull free(arena);
77 7a4ee46d 2003-11-23 devnull }
78 7a4ee46d 2003-11-23 devnull
79 7a4ee46d 2003-11-23 devnull Arena*
80 7a4ee46d 2003-11-23 devnull newarena(Part *part, char *name, u64int base, u64int size, u32int blocksize)
81 7a4ee46d 2003-11-23 devnull {
82 7a4ee46d 2003-11-23 devnull Arena *arena;
83 7a4ee46d 2003-11-23 devnull
84 7a4ee46d 2003-11-23 devnull if(nameok(name) < 0){
85 7a4ee46d 2003-11-23 devnull seterr(EOk, "illegal arena name", name);
86 7a4ee46d 2003-11-23 devnull return nil;
87 7a4ee46d 2003-11-23 devnull }
88 7a4ee46d 2003-11-23 devnull arena = MKZ(Arena);
89 7a4ee46d 2003-11-23 devnull arena->part = part;
90 7a4ee46d 2003-11-23 devnull arena->version = ArenaVersion;
91 7a4ee46d 2003-11-23 devnull arena->blocksize = blocksize;
92 7a4ee46d 2003-11-23 devnull arena->clumpmax = arena->blocksize / ClumpInfoSize;
93 7a4ee46d 2003-11-23 devnull arena->base = base + blocksize;
94 7a4ee46d 2003-11-23 devnull arena->size = size - 2 * blocksize;
95 7a4ee46d 2003-11-23 devnull
96 7a4ee46d 2003-11-23 devnull namecp(arena->name, name);
97 7a4ee46d 2003-11-23 devnull
98 7a4ee46d 2003-11-23 devnull if(wbarena(arena)<0 || wbarenahead(arena)<0){
99 7a4ee46d 2003-11-23 devnull freearena(arena);
100 7a4ee46d 2003-11-23 devnull return nil;
101 7a4ee46d 2003-11-23 devnull }
102 7a4ee46d 2003-11-23 devnull
103 7a4ee46d 2003-11-23 devnull return arena;
104 7a4ee46d 2003-11-23 devnull }
105 7a4ee46d 2003-11-23 devnull
106 7a4ee46d 2003-11-23 devnull int
107 7a4ee46d 2003-11-23 devnull readclumpinfo(Arena *arena, int clump, ClumpInfo *ci)
108 7a4ee46d 2003-11-23 devnull {
109 7a4ee46d 2003-11-23 devnull CIBlock *cib, r;
110 7a4ee46d 2003-11-23 devnull
111 7a4ee46d 2003-11-23 devnull cib = getcib(arena, clump, 0, &r);
112 7a4ee46d 2003-11-23 devnull if(cib == nil)
113 7a4ee46d 2003-11-23 devnull return -1;
114 7a4ee46d 2003-11-23 devnull unpackclumpinfo(ci, &cib->data->data[cib->offset]);
115 7a4ee46d 2003-11-23 devnull putcib(arena, cib);
116 7a4ee46d 2003-11-23 devnull return 0;
117 7a4ee46d 2003-11-23 devnull }
118 7a4ee46d 2003-11-23 devnull
119 7a4ee46d 2003-11-23 devnull int
120 7a4ee46d 2003-11-23 devnull readclumpinfos(Arena *arena, int clump, ClumpInfo *cis, int n)
121 7a4ee46d 2003-11-23 devnull {
122 7a4ee46d 2003-11-23 devnull CIBlock *cib, r;
123 7a4ee46d 2003-11-23 devnull int i;
124 7a4ee46d 2003-11-23 devnull
125 7a4ee46d 2003-11-23 devnull for(i = 0; i < n; i++){
126 7a4ee46d 2003-11-23 devnull cib = getcib(arena, clump + i, 0, &r);
127 7a4ee46d 2003-11-23 devnull if(cib == nil)
128 7a4ee46d 2003-11-23 devnull break;
129 7a4ee46d 2003-11-23 devnull unpackclumpinfo(&cis[i], &cib->data->data[cib->offset]);
130 7a4ee46d 2003-11-23 devnull putcib(arena, cib);
131 7a4ee46d 2003-11-23 devnull }
132 7a4ee46d 2003-11-23 devnull return i;
133 7a4ee46d 2003-11-23 devnull }
134 7a4ee46d 2003-11-23 devnull
135 7a4ee46d 2003-11-23 devnull /*
136 7a4ee46d 2003-11-23 devnull * write directory information for one clump
137 7a4ee46d 2003-11-23 devnull * must be called the arena locked
138 7a4ee46d 2003-11-23 devnull */
139 7a4ee46d 2003-11-23 devnull int
140 7a4ee46d 2003-11-23 devnull writeclumpinfo(Arena *arena, int clump, ClumpInfo *ci)
141 7a4ee46d 2003-11-23 devnull {
142 7a4ee46d 2003-11-23 devnull CIBlock *cib, r;
143 7a4ee46d 2003-11-23 devnull
144 7a4ee46d 2003-11-23 devnull cib = getcib(arena, clump, 1, &r);
145 7a4ee46d 2003-11-23 devnull if(cib == nil)
146 7a4ee46d 2003-11-23 devnull return -1;
147 24998851 2004-03-11 devnull dirtydblock(cib->data, DirtyArenaCib);
148 7a4ee46d 2003-11-23 devnull packclumpinfo(ci, &cib->data->data[cib->offset]);
149 7a4ee46d 2003-11-23 devnull putcib(arena, cib);
150 7a4ee46d 2003-11-23 devnull return 0;
151 7a4ee46d 2003-11-23 devnull }
152 7a4ee46d 2003-11-23 devnull
153 7a4ee46d 2003-11-23 devnull u64int
154 7a4ee46d 2003-11-23 devnull arenadirsize(Arena *arena, u32int clumps)
155 7a4ee46d 2003-11-23 devnull {
156 7a4ee46d 2003-11-23 devnull return ((clumps / arena->clumpmax) + 1) * arena->blocksize;
157 7a4ee46d 2003-11-23 devnull }
158 7a4ee46d 2003-11-23 devnull
159 7a4ee46d 2003-11-23 devnull /*
160 7a4ee46d 2003-11-23 devnull * read a clump of data
161 7a4ee46d 2003-11-23 devnull * n is a hint of the size of the data, not including the header
162 7a4ee46d 2003-11-23 devnull * make sure it won't run off the end, then return the number of bytes actually read
163 7a4ee46d 2003-11-23 devnull */
164 7a4ee46d 2003-11-23 devnull u32int
165 7a4ee46d 2003-11-23 devnull readarena(Arena *arena, u64int aa, u8int *buf, long n)
166 7a4ee46d 2003-11-23 devnull {
167 7a4ee46d 2003-11-23 devnull DBlock *b;
168 7a4ee46d 2003-11-23 devnull u64int a;
169 7a4ee46d 2003-11-23 devnull u32int blocksize, off, m;
170 7a4ee46d 2003-11-23 devnull long nn;
171 7a4ee46d 2003-11-23 devnull
172 7a4ee46d 2003-11-23 devnull if(n == 0)
173 7a4ee46d 2003-11-23 devnull return -1;
174 7a4ee46d 2003-11-23 devnull
175 7a4ee46d 2003-11-23 devnull qlock(&arena->lock);
176 7a4ee46d 2003-11-23 devnull a = arena->size - arenadirsize(arena, arena->clumps);
177 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
178 7a4ee46d 2003-11-23 devnull if(aa >= a){
179 7a4ee46d 2003-11-23 devnull seterr(EOk, "reading beyond arena clump storage: clumps=%d aa=%lld a=%lld -1 clumps=%lld\n", arena->clumps, aa, a, arena->size - arenadirsize(arena, arena->clumps - 1));
180 7a4ee46d 2003-11-23 devnull return -1;
181 7a4ee46d 2003-11-23 devnull }
182 7a4ee46d 2003-11-23 devnull if(aa + n > a)
183 7a4ee46d 2003-11-23 devnull n = a - aa;
184 7a4ee46d 2003-11-23 devnull
185 7a4ee46d 2003-11-23 devnull blocksize = arena->blocksize;
186 7a4ee46d 2003-11-23 devnull a = arena->base + aa;
187 7a4ee46d 2003-11-23 devnull off = a & (blocksize - 1);
188 7a4ee46d 2003-11-23 devnull a -= off;
189 7a4ee46d 2003-11-23 devnull nn = 0;
190 7a4ee46d 2003-11-23 devnull for(;;){
191 7a4ee46d 2003-11-23 devnull b = getdblock(arena->part, a, 1);
192 7a4ee46d 2003-11-23 devnull if(b == nil)
193 7a4ee46d 2003-11-23 devnull return -1;
194 7a4ee46d 2003-11-23 devnull m = blocksize - off;
195 7a4ee46d 2003-11-23 devnull if(m > n - nn)
196 7a4ee46d 2003-11-23 devnull m = n - nn;
197 7a4ee46d 2003-11-23 devnull memmove(&buf[nn], &b->data[off], m);
198 7a4ee46d 2003-11-23 devnull putdblock(b);
199 7a4ee46d 2003-11-23 devnull nn += m;
200 7a4ee46d 2003-11-23 devnull if(nn == n)
201 7a4ee46d 2003-11-23 devnull break;
202 7a4ee46d 2003-11-23 devnull off = 0;
203 7a4ee46d 2003-11-23 devnull a += blocksize;
204 7a4ee46d 2003-11-23 devnull }
205 7a4ee46d 2003-11-23 devnull return n;
206 7a4ee46d 2003-11-23 devnull }
207 7a4ee46d 2003-11-23 devnull
208 7a4ee46d 2003-11-23 devnull /*
209 7a4ee46d 2003-11-23 devnull * write some data to the clump section at a given offset
210 7a4ee46d 2003-11-23 devnull * used to fix up corrupted arenas.
211 7a4ee46d 2003-11-23 devnull */
212 7a4ee46d 2003-11-23 devnull u32int
213 7a4ee46d 2003-11-23 devnull writearena(Arena *arena, u64int aa, u8int *clbuf, u32int n)
214 7a4ee46d 2003-11-23 devnull {
215 7a4ee46d 2003-11-23 devnull DBlock *b;
216 7a4ee46d 2003-11-23 devnull u64int a;
217 7a4ee46d 2003-11-23 devnull u32int blocksize, off, m;
218 7a4ee46d 2003-11-23 devnull long nn;
219 7a4ee46d 2003-11-23 devnull int ok;
220 7a4ee46d 2003-11-23 devnull
221 7a4ee46d 2003-11-23 devnull if(n == 0)
222 7a4ee46d 2003-11-23 devnull return -1;
223 7a4ee46d 2003-11-23 devnull
224 7a4ee46d 2003-11-23 devnull qlock(&arena->lock);
225 7a4ee46d 2003-11-23 devnull a = arena->size - arenadirsize(arena, arena->clumps);
226 7a4ee46d 2003-11-23 devnull if(aa >= a || aa + n > a){
227 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
228 7a4ee46d 2003-11-23 devnull seterr(EOk, "writing beyond arena clump storage");
229 7a4ee46d 2003-11-23 devnull return -1;
230 7a4ee46d 2003-11-23 devnull }
231 7a4ee46d 2003-11-23 devnull
232 7a4ee46d 2003-11-23 devnull blocksize = arena->blocksize;
233 7a4ee46d 2003-11-23 devnull a = arena->base + aa;
234 7a4ee46d 2003-11-23 devnull off = a & (blocksize - 1);
235 7a4ee46d 2003-11-23 devnull a -= off;
236 7a4ee46d 2003-11-23 devnull nn = 0;
237 7a4ee46d 2003-11-23 devnull for(;;){
238 7a4ee46d 2003-11-23 devnull b = getdblock(arena->part, a, off != 0 || off + n < blocksize);
239 7a4ee46d 2003-11-23 devnull if(b == nil){
240 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
241 7a4ee46d 2003-11-23 devnull return -1;
242 7a4ee46d 2003-11-23 devnull }
243 24998851 2004-03-11 devnull dirtydblock(b, DirtyArena);
244 7a4ee46d 2003-11-23 devnull m = blocksize - off;
245 7a4ee46d 2003-11-23 devnull if(m > n - nn)
246 7a4ee46d 2003-11-23 devnull m = n - nn;
247 7a4ee46d 2003-11-23 devnull memmove(&b->data[off], &clbuf[nn], m);
248 24998851 2004-03-11 devnull // ok = writepart(arena->part, a, b->data, blocksize);
249 24998851 2004-03-11 devnull ok = 0;
250 7a4ee46d 2003-11-23 devnull putdblock(b);
251 7a4ee46d 2003-11-23 devnull if(ok < 0){
252 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
253 7a4ee46d 2003-11-23 devnull return -1;
254 7a4ee46d 2003-11-23 devnull }
255 7a4ee46d 2003-11-23 devnull nn += m;
256 7a4ee46d 2003-11-23 devnull if(nn == n)
257 7a4ee46d 2003-11-23 devnull break;
258 7a4ee46d 2003-11-23 devnull off = 0;
259 7a4ee46d 2003-11-23 devnull a += blocksize;
260 7a4ee46d 2003-11-23 devnull }
261 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
262 7a4ee46d 2003-11-23 devnull return n;
263 7a4ee46d 2003-11-23 devnull }
264 7a4ee46d 2003-11-23 devnull
265 7a4ee46d 2003-11-23 devnull /*
266 7a4ee46d 2003-11-23 devnull * allocate space for the clump and write it,
267 7a4ee46d 2003-11-23 devnull * updating the arena directory
268 7a4ee46d 2003-11-23 devnull ZZZ question: should this distinguish between an arena
269 7a4ee46d 2003-11-23 devnull filling up and real errors writing the clump?
270 7a4ee46d 2003-11-23 devnull */
271 7a4ee46d 2003-11-23 devnull u64int
272 7a4ee46d 2003-11-23 devnull writeaclump(Arena *arena, Clump *c, u8int *clbuf)
273 7a4ee46d 2003-11-23 devnull {
274 7a4ee46d 2003-11-23 devnull DBlock *b;
275 7a4ee46d 2003-11-23 devnull u64int a, aa;
276 7a4ee46d 2003-11-23 devnull u32int clump, n, nn, m, off, blocksize;
277 7a4ee46d 2003-11-23 devnull int ok;
278 7a4ee46d 2003-11-23 devnull
279 7a4ee46d 2003-11-23 devnull n = c->info.size + ClumpSize;
280 7a4ee46d 2003-11-23 devnull qlock(&arena->lock);
281 7a4ee46d 2003-11-23 devnull aa = arena->used;
282 7a4ee46d 2003-11-23 devnull if(arena->sealed
283 7a4ee46d 2003-11-23 devnull || aa + n + U32Size + arenadirsize(arena, arena->clumps + 1) > arena->size){
284 7a4ee46d 2003-11-23 devnull if(!arena->sealed)
285 7a4ee46d 2003-11-23 devnull sealarena(arena);
286 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
287 7a4ee46d 2003-11-23 devnull return TWID64;
288 7a4ee46d 2003-11-23 devnull }
289 7a4ee46d 2003-11-23 devnull if(packclump(c, &clbuf[0]) < 0){
290 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
291 7a4ee46d 2003-11-23 devnull return TWID64;
292 7a4ee46d 2003-11-23 devnull }
293 7a4ee46d 2003-11-23 devnull
294 7a4ee46d 2003-11-23 devnull /*
295 7a4ee46d 2003-11-23 devnull * write the data out one block at a time
296 7a4ee46d 2003-11-23 devnull */
297 7a4ee46d 2003-11-23 devnull blocksize = arena->blocksize;
298 7a4ee46d 2003-11-23 devnull a = arena->base + aa;
299 7a4ee46d 2003-11-23 devnull off = a & (blocksize - 1);
300 7a4ee46d 2003-11-23 devnull a -= off;
301 7a4ee46d 2003-11-23 devnull nn = 0;
302 7a4ee46d 2003-11-23 devnull for(;;){
303 7a4ee46d 2003-11-23 devnull b = getdblock(arena->part, a, off != 0);
304 7a4ee46d 2003-11-23 devnull if(b == nil){
305 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
306 7a4ee46d 2003-11-23 devnull return TWID64;
307 7a4ee46d 2003-11-23 devnull }
308 24998851 2004-03-11 devnull dirtydblock(b, DirtyArena);
309 7a4ee46d 2003-11-23 devnull m = blocksize - off;
310 7a4ee46d 2003-11-23 devnull if(m > n - nn)
311 7a4ee46d 2003-11-23 devnull m = n - nn;
312 7a4ee46d 2003-11-23 devnull memmove(&b->data[off], &clbuf[nn], m);
313 24998851 2004-03-11 devnull // ok = writepart(arena->part, a, b->data, blocksize);
314 24998851 2004-03-11 devnull ok = 0;
315 7a4ee46d 2003-11-23 devnull putdblock(b);
316 7a4ee46d 2003-11-23 devnull if(ok < 0){
317 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
318 7a4ee46d 2003-11-23 devnull return TWID64;
319 7a4ee46d 2003-11-23 devnull }
320 7a4ee46d 2003-11-23 devnull nn += m;
321 7a4ee46d 2003-11-23 devnull if(nn == n)
322 7a4ee46d 2003-11-23 devnull break;
323 7a4ee46d 2003-11-23 devnull off = 0;
324 7a4ee46d 2003-11-23 devnull a += blocksize;
325 7a4ee46d 2003-11-23 devnull }
326 7a4ee46d 2003-11-23 devnull
327 7a4ee46d 2003-11-23 devnull arena->used += c->info.size + ClumpSize;
328 7a4ee46d 2003-11-23 devnull arena->uncsize += c->info.uncsize;
329 7a4ee46d 2003-11-23 devnull if(c->info.size < c->info.uncsize)
330 7a4ee46d 2003-11-23 devnull arena->cclumps++;
331 7a4ee46d 2003-11-23 devnull
332 7a4ee46d 2003-11-23 devnull clump = arena->clumps++;
333 7a4ee46d 2003-11-23 devnull if(arena->clumps == 0)
334 7a4ee46d 2003-11-23 devnull sysfatal("clumps wrapped\n");
335 7a4ee46d 2003-11-23 devnull arena->wtime = now();
336 7a4ee46d 2003-11-23 devnull if(arena->ctime == 0)
337 7a4ee46d 2003-11-23 devnull arena->ctime = arena->wtime;
338 7a4ee46d 2003-11-23 devnull
339 7a4ee46d 2003-11-23 devnull writeclumpinfo(arena, clump, &c->info);
340 7a4ee46d 2003-11-23 devnull //ZZZ make this an enum param
341 7a4ee46d 2003-11-23 devnull if((clump & 0x1ff) == 0x1ff){
342 7a4ee46d 2003-11-23 devnull flushciblocks(arena);
343 7a4ee46d 2003-11-23 devnull wbarena(arena);
344 7a4ee46d 2003-11-23 devnull }
345 7a4ee46d 2003-11-23 devnull
346 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
347 7a4ee46d 2003-11-23 devnull return aa;
348 7a4ee46d 2003-11-23 devnull }
349 7a4ee46d 2003-11-23 devnull
350 7a4ee46d 2003-11-23 devnull /*
351 7a4ee46d 2003-11-23 devnull * once sealed, an arena never has any data added to it.
352 7a4ee46d 2003-11-23 devnull * it should only be changed to fix errors.
353 7a4ee46d 2003-11-23 devnull * this also syncs the clump directory.
354 7a4ee46d 2003-11-23 devnull */
355 7a4ee46d 2003-11-23 devnull static void
356 7a4ee46d 2003-11-23 devnull sealarena(Arena *arena)
357 7a4ee46d 2003-11-23 devnull {
358 7a4ee46d 2003-11-23 devnull flushciblocks(arena);
359 24998851 2004-03-11 devnull flushdcache();
360 7a4ee46d 2003-11-23 devnull arena->sealed = 1;
361 7a4ee46d 2003-11-23 devnull wbarena(arena);
362 7a4ee46d 2003-11-23 devnull backsumarena(arena);
363 7a4ee46d 2003-11-23 devnull }
364 7a4ee46d 2003-11-23 devnull
365 7a4ee46d 2003-11-23 devnull void
366 7a4ee46d 2003-11-23 devnull backsumarena(Arena *arena)
367 7a4ee46d 2003-11-23 devnull {
368 7a4ee46d 2003-11-23 devnull ASum *as;
369 7a4ee46d 2003-11-23 devnull
370 7a4ee46d 2003-11-23 devnull as = MK(ASum);
371 7a4ee46d 2003-11-23 devnull if(as == nil)
372 7a4ee46d 2003-11-23 devnull return;
373 7a4ee46d 2003-11-23 devnull qlock(&sumlock);
374 7a4ee46d 2003-11-23 devnull as->arena = arena;
375 7a4ee46d 2003-11-23 devnull as->next = sumq;
376 7a4ee46d 2003-11-23 devnull sumq = as;
377 7a4ee46d 2003-11-23 devnull rwakeup(&sumwait);
378 7a4ee46d 2003-11-23 devnull qunlock(&sumlock);
379 7a4ee46d 2003-11-23 devnull }
380 7a4ee46d 2003-11-23 devnull
381 7a4ee46d 2003-11-23 devnull static void
382 7a4ee46d 2003-11-23 devnull sumproc(void *unused)
383 7a4ee46d 2003-11-23 devnull {
384 7a4ee46d 2003-11-23 devnull ASum *as;
385 7a4ee46d 2003-11-23 devnull Arena *arena;
386 7a4ee46d 2003-11-23 devnull
387 7a4ee46d 2003-11-23 devnull USED(unused);
388 7a4ee46d 2003-11-23 devnull
389 7a4ee46d 2003-11-23 devnull for(;;){
390 7a4ee46d 2003-11-23 devnull qlock(&sumlock);
391 7a4ee46d 2003-11-23 devnull while(sumq == nil)
392 7a4ee46d 2003-11-23 devnull rsleep(&sumwait);
393 7a4ee46d 2003-11-23 devnull as = sumq;
394 7a4ee46d 2003-11-23 devnull sumq = as->next;
395 7a4ee46d 2003-11-23 devnull qunlock(&sumlock);
396 7a4ee46d 2003-11-23 devnull arena = as->arena;
397 7a4ee46d 2003-11-23 devnull free(as);
398 7a4ee46d 2003-11-23 devnull
399 7a4ee46d 2003-11-23 devnull sumarena(arena);
400 7a4ee46d 2003-11-23 devnull }
401 7a4ee46d 2003-11-23 devnull }
402 7a4ee46d 2003-11-23 devnull
403 7a4ee46d 2003-11-23 devnull void
404 7a4ee46d 2003-11-23 devnull sumarena(Arena *arena)
405 7a4ee46d 2003-11-23 devnull {
406 7a4ee46d 2003-11-23 devnull ZBlock *b;
407 7a4ee46d 2003-11-23 devnull DigestState s;
408 7a4ee46d 2003-11-23 devnull u64int a, e;
409 7a4ee46d 2003-11-23 devnull u32int bs;
410 7a4ee46d 2003-11-23 devnull u8int score[VtScoreSize];
411 7a4ee46d 2003-11-23 devnull
412 7a4ee46d 2003-11-23 devnull bs = MaxIoSize;
413 7a4ee46d 2003-11-23 devnull if(bs < arena->blocksize)
414 7a4ee46d 2003-11-23 devnull bs = arena->blocksize;
415 7a4ee46d 2003-11-23 devnull
416 7a4ee46d 2003-11-23 devnull /*
417 7a4ee46d 2003-11-23 devnull * read & sum all blocks except the last one
418 7a4ee46d 2003-11-23 devnull */
419 7a4ee46d 2003-11-23 devnull memset(&s, 0, sizeof s);
420 7a4ee46d 2003-11-23 devnull b = alloczblock(bs, 0);
421 7a4ee46d 2003-11-23 devnull e = arena->base + arena->size;
422 7a4ee46d 2003-11-23 devnull for(a = arena->base - arena->blocksize; a + arena->blocksize <= e; a += bs){
423 7a4ee46d 2003-11-23 devnull if(a + bs > e)
424 7a4ee46d 2003-11-23 devnull bs = arena->blocksize;
425 7a4ee46d 2003-11-23 devnull if(readpart(arena->part, a, b->data, bs) < 0)
426 7a4ee46d 2003-11-23 devnull goto ReadErr;
427 7a4ee46d 2003-11-23 devnull sha1(b->data, bs, nil, &s);
428 7a4ee46d 2003-11-23 devnull }
429 7a4ee46d 2003-11-23 devnull
430 7a4ee46d 2003-11-23 devnull /*
431 7a4ee46d 2003-11-23 devnull * the last one is special, since it may already have the checksum included
432 7a4ee46d 2003-11-23 devnull */
433 7a4ee46d 2003-11-23 devnull bs = arena->blocksize;
434 7a4ee46d 2003-11-23 devnull if(readpart(arena->part, e, b->data, bs) < 0){
435 7a4ee46d 2003-11-23 devnull ReadErr:
436 7a4ee46d 2003-11-23 devnull logerr(EOk, "sumarena can't sum %s, read at %lld failed: %r", arena->name, a);
437 7a4ee46d 2003-11-23 devnull freezblock(b);
438 7a4ee46d 2003-11-23 devnull return;
439 7a4ee46d 2003-11-23 devnull }
440 7a4ee46d 2003-11-23 devnull
441 7a4ee46d 2003-11-23 devnull sha1(b->data, bs-VtScoreSize, nil, &s);
442 7a4ee46d 2003-11-23 devnull sha1(zeroscore, VtScoreSize, nil, &s);
443 7a4ee46d 2003-11-23 devnull sha1(nil, 0, score, &s);
444 7a4ee46d 2003-11-23 devnull
445 7a4ee46d 2003-11-23 devnull /*
446 7a4ee46d 2003-11-23 devnull * check for no checksum or the same
447 24998851 2004-03-11 devnull *
448 24998851 2004-03-11 devnull * the writepart is okay because we flushed the dcache in sealarena
449 7a4ee46d 2003-11-23 devnull */
450 7a4ee46d 2003-11-23 devnull if(scorecmp(score, &b->data[bs - VtScoreSize]) != 0){
451 7a4ee46d 2003-11-23 devnull if(scorecmp(zeroscore, &b->data[bs - VtScoreSize]) != 0)
452 7a4ee46d 2003-11-23 devnull logerr(EOk, "overwriting mismatched checksums for arena=%s, found=%V calculated=%V",
453 7a4ee46d 2003-11-23 devnull arena->name, &b->data[bs - VtScoreSize], score);
454 7a4ee46d 2003-11-23 devnull scorecp(&b->data[bs - VtScoreSize], score);
455 7a4ee46d 2003-11-23 devnull if(writepart(arena->part, e, b->data, bs) < 0)
456 7a4ee46d 2003-11-23 devnull logerr(EOk, "sumarena can't write sum for %s: %r", arena->name);
457 7a4ee46d 2003-11-23 devnull }
458 7a4ee46d 2003-11-23 devnull freezblock(b);
459 7a4ee46d 2003-11-23 devnull
460 7a4ee46d 2003-11-23 devnull qlock(&arena->lock);
461 7a4ee46d 2003-11-23 devnull scorecp(arena->score, score);
462 7a4ee46d 2003-11-23 devnull qunlock(&arena->lock);
463 7a4ee46d 2003-11-23 devnull }
464 7a4ee46d 2003-11-23 devnull
465 7a4ee46d 2003-11-23 devnull /*
466 7a4ee46d 2003-11-23 devnull * write the arena trailer block to the partition
467 7a4ee46d 2003-11-23 devnull */
468 7a4ee46d 2003-11-23 devnull int
469 7a4ee46d 2003-11-23 devnull wbarena(Arena *arena)
470 7a4ee46d 2003-11-23 devnull {
471 333c1dcc 2004-03-13 devnull DBlock *b;
472 7a4ee46d 2003-11-23 devnull int bad;
473 7a4ee46d 2003-11-23 devnull
474 333c1dcc 2004-03-13 devnull if((b = getdblock(arena->part, arena->base + arena->size, 0)) == nil){
475 7a4ee46d 2003-11-23 devnull logerr(EAdmin, "can't write arena trailer: %r");
476 7a4ee46d 2003-11-23 devnull return -1;
477 7a4ee46d 2003-11-23 devnull }
478 333c1dcc 2004-03-13 devnull dirtydblock(b, DirtyArenaTrailer);
479 333c1dcc 2004-03-13 devnull bad = okarena(arena)<0 || packarena(arena, b->data)<0;
480 333c1dcc 2004-03-13 devnull putdblock(b);
481 7a4ee46d 2003-11-23 devnull if(bad)
482 7a4ee46d 2003-11-23 devnull return -1;
483 7a4ee46d 2003-11-23 devnull return 0;
484 7a4ee46d 2003-11-23 devnull }
485 7a4ee46d 2003-11-23 devnull
486 7a4ee46d 2003-11-23 devnull int
487 7a4ee46d 2003-11-23 devnull wbarenahead(Arena *arena)
488 7a4ee46d 2003-11-23 devnull {
489 7a4ee46d 2003-11-23 devnull ZBlock *b;
490 7a4ee46d 2003-11-23 devnull ArenaHead head;
491 7a4ee46d 2003-11-23 devnull int bad;
492 7a4ee46d 2003-11-23 devnull
493 7a4ee46d 2003-11-23 devnull namecp(head.name, arena->name);
494 7a4ee46d 2003-11-23 devnull head.version = arena->version;
495 7a4ee46d 2003-11-23 devnull head.size = arena->size + 2 * arena->blocksize;
496 7a4ee46d 2003-11-23 devnull head.blocksize = arena->blocksize;
497 7a4ee46d 2003-11-23 devnull b = alloczblock(arena->blocksize, 1);
498 7a4ee46d 2003-11-23 devnull if(b == nil){
499 7a4ee46d 2003-11-23 devnull logerr(EAdmin, "can't write arena header: %r");
500 7a4ee46d 2003-11-23 devnull ///ZZZ add error message?
501 7a4ee46d 2003-11-23 devnull return -1;
502 7a4ee46d 2003-11-23 devnull }
503 333c1dcc 2004-03-13 devnull /*
504 333c1dcc 2004-03-13 devnull * this writepart is okay because it only happens
505 333c1dcc 2004-03-13 devnull * during initialization.
506 333c1dcc 2004-03-13 devnull */
507 7a4ee46d 2003-11-23 devnull bad = packarenahead(&head, b->data)<0 ||
508 7a4ee46d 2003-11-23 devnull writepart(arena->part, arena->base - arena->blocksize, b->data, arena->blocksize)<0;
509 7a4ee46d 2003-11-23 devnull freezblock(b);
510 7a4ee46d 2003-11-23 devnull if(bad)
511 7a4ee46d 2003-11-23 devnull return -1;
512 7a4ee46d 2003-11-23 devnull return 0;
513 7a4ee46d 2003-11-23 devnull }
514 7a4ee46d 2003-11-23 devnull
515 7a4ee46d 2003-11-23 devnull /*
516 7a4ee46d 2003-11-23 devnull * read the arena header and trailer blocks from disk
517 7a4ee46d 2003-11-23 devnull */
518 7a4ee46d 2003-11-23 devnull static int
519 7a4ee46d 2003-11-23 devnull loadarena(Arena *arena)
520 7a4ee46d 2003-11-23 devnull {
521 7a4ee46d 2003-11-23 devnull ArenaHead head;
522 7a4ee46d 2003-11-23 devnull ZBlock *b;
523 7a4ee46d 2003-11-23 devnull
524 7a4ee46d 2003-11-23 devnull b = alloczblock(arena->blocksize, 0);
525 7a4ee46d 2003-11-23 devnull if(b == nil)
526 7a4ee46d 2003-11-23 devnull return -1;
527 7a4ee46d 2003-11-23 devnull if(readpart(arena->part, arena->base + arena->size, b->data, arena->blocksize) < 0){
528 7a4ee46d 2003-11-23 devnull freezblock(b);
529 7a4ee46d 2003-11-23 devnull return -1;
530 7a4ee46d 2003-11-23 devnull }
531 7a4ee46d 2003-11-23 devnull if(unpackarena(arena, b->data) < 0){
532 7a4ee46d 2003-11-23 devnull freezblock(b);
533 7a4ee46d 2003-11-23 devnull return -1;
534 7a4ee46d 2003-11-23 devnull }
535 7a4ee46d 2003-11-23 devnull if(arena->version != ArenaVersion){
536 7a4ee46d 2003-11-23 devnull seterr(EAdmin, "unknown arena version %d", arena->version);
537 7a4ee46d 2003-11-23 devnull freezblock(b);
538 7a4ee46d 2003-11-23 devnull return -1;
539 7a4ee46d 2003-11-23 devnull }
540 7a4ee46d 2003-11-23 devnull scorecp(arena->score, &b->data[arena->blocksize - VtScoreSize]);
541 7a4ee46d 2003-11-23 devnull
542 7a4ee46d 2003-11-23 devnull if(readpart(arena->part, arena->base - arena->blocksize, b->data, arena->blocksize) < 0){
543 7a4ee46d 2003-11-23 devnull logerr(EAdmin, "can't read arena header: %r");
544 7a4ee46d 2003-11-23 devnull freezblock(b);
545 7a4ee46d 2003-11-23 devnull return 0;
546 7a4ee46d 2003-11-23 devnull }
547 7a4ee46d 2003-11-23 devnull if(unpackarenahead(&head, b->data) < 0)
548 7a4ee46d 2003-11-23 devnull logerr(ECorrupt, "corrupted arena header: %r");
549 7a4ee46d 2003-11-23 devnull else if(namecmp(arena->name, head.name)!=0
550 7a4ee46d 2003-11-23 devnull || arena->version != head.version
551 7a4ee46d 2003-11-23 devnull || arena->blocksize != head.blocksize
552 7a4ee46d 2003-11-23 devnull || arena->size + 2 * arena->blocksize != head.size)
553 7a4ee46d 2003-11-23 devnull logerr(ECorrupt, "arena header inconsistent with arena data");
554 7a4ee46d 2003-11-23 devnull freezblock(b);
555 7a4ee46d 2003-11-23 devnull
556 7a4ee46d 2003-11-23 devnull return 0;
557 7a4ee46d 2003-11-23 devnull }
558 7a4ee46d 2003-11-23 devnull
559 7a4ee46d 2003-11-23 devnull static int
560 7a4ee46d 2003-11-23 devnull okarena(Arena *arena)
561 7a4ee46d 2003-11-23 devnull {
562 7a4ee46d 2003-11-23 devnull u64int dsize;
563 7a4ee46d 2003-11-23 devnull int ok;
564 7a4ee46d 2003-11-23 devnull
565 7a4ee46d 2003-11-23 devnull ok = 0;
566 7a4ee46d 2003-11-23 devnull dsize = arenadirsize(arena, arena->clumps);
567 7a4ee46d 2003-11-23 devnull if(arena->used + dsize > arena->size){
568 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "arena used > size");
569 7a4ee46d 2003-11-23 devnull ok = -1;
570 7a4ee46d 2003-11-23 devnull }
571 7a4ee46d 2003-11-23 devnull
572 7a4ee46d 2003-11-23 devnull if(arena->cclumps > arena->clumps)
573 7a4ee46d 2003-11-23 devnull logerr(ECorrupt, "arena has more compressed clumps than total clumps");
574 7a4ee46d 2003-11-23 devnull
575 7a4ee46d 2003-11-23 devnull if(arena->uncsize + arena->clumps * ClumpSize + arena->blocksize < arena->used)
576 7a4ee46d 2003-11-23 devnull logerr(ECorrupt, "arena uncompressed size inconsistent with used space %lld %d %lld", arena->uncsize, arena->clumps, arena->used);
577 7a4ee46d 2003-11-23 devnull
578 7a4ee46d 2003-11-23 devnull if(arena->ctime > arena->wtime)
579 7a4ee46d 2003-11-23 devnull logerr(ECorrupt, "arena creation time after last write time");
580 7a4ee46d 2003-11-23 devnull
581 7a4ee46d 2003-11-23 devnull return ok;
582 7a4ee46d 2003-11-23 devnull }
583 7a4ee46d 2003-11-23 devnull
584 7a4ee46d 2003-11-23 devnull static CIBlock*
585 7a4ee46d 2003-11-23 devnull getcib(Arena *arena, int clump, int writing, CIBlock *rock)
586 7a4ee46d 2003-11-23 devnull {
587 333c1dcc 2004-03-13 devnull int read;
588 7a4ee46d 2003-11-23 devnull CIBlock *cib;
589 7a4ee46d 2003-11-23 devnull u32int block, off;
590 7a4ee46d 2003-11-23 devnull
591 7a4ee46d 2003-11-23 devnull if(clump >= arena->clumps){
592 7a4ee46d 2003-11-23 devnull seterr(EOk, "clump directory access out of range");
593 7a4ee46d 2003-11-23 devnull return nil;
594 7a4ee46d 2003-11-23 devnull }
595 7a4ee46d 2003-11-23 devnull block = clump / arena->clumpmax;
596 7a4ee46d 2003-11-23 devnull off = (clump - block * arena->clumpmax) * ClumpInfoSize;
597 7a4ee46d 2003-11-23 devnull
598 24998851 2004-03-11 devnull /*
599 7a4ee46d 2003-11-23 devnull if(arena->cib.block == block
600 7a4ee46d 2003-11-23 devnull && arena->cib.data != nil){
601 7a4ee46d 2003-11-23 devnull arena->cib.offset = off;
602 7a4ee46d 2003-11-23 devnull return &arena->cib;
603 7a4ee46d 2003-11-23 devnull }
604 7a4ee46d 2003-11-23 devnull
605 7a4ee46d 2003-11-23 devnull if(writing){
606 7a4ee46d 2003-11-23 devnull flushciblocks(arena);
607 7a4ee46d 2003-11-23 devnull cib = &arena->cib;
608 7a4ee46d 2003-11-23 devnull }else
609 7a4ee46d 2003-11-23 devnull cib = rock;
610 24998851 2004-03-11 devnull */
611 24998851 2004-03-11 devnull cib = rock;
612 7a4ee46d 2003-11-23 devnull
613 7a4ee46d 2003-11-23 devnull qlock(&stats.lock);
614 7a4ee46d 2003-11-23 devnull stats.cireads++;
615 7a4ee46d 2003-11-23 devnull qunlock(&stats.lock);
616 7a4ee46d 2003-11-23 devnull
617 7a4ee46d 2003-11-23 devnull cib->block = block;
618 7a4ee46d 2003-11-23 devnull cib->offset = off;
619 333c1dcc 2004-03-13 devnull
620 333c1dcc 2004-03-13 devnull read = 1;
621 333c1dcc 2004-03-13 devnull if(writing && off == 0 && clump == arena->clumps-1)
622 333c1dcc 2004-03-13 devnull read = 0;
623 333c1dcc 2004-03-13 devnull
624 333c1dcc 2004-03-13 devnull cib->data = getdblock(arena->part, arena->base + arena->size - (block + 1) * arena->blocksize, read);
625 7a4ee46d 2003-11-23 devnull if(cib->data == nil)
626 7a4ee46d 2003-11-23 devnull return nil;
627 7a4ee46d 2003-11-23 devnull return cib;
628 7a4ee46d 2003-11-23 devnull }
629 7a4ee46d 2003-11-23 devnull
630 7a4ee46d 2003-11-23 devnull static void
631 7a4ee46d 2003-11-23 devnull putcib(Arena *arena, CIBlock *cib)
632 7a4ee46d 2003-11-23 devnull {
633 7a4ee46d 2003-11-23 devnull if(cib != &arena->cib){
634 7a4ee46d 2003-11-23 devnull putdblock(cib->data);
635 7a4ee46d 2003-11-23 devnull cib->data = nil;
636 7a4ee46d 2003-11-23 devnull }
637 7a4ee46d 2003-11-23 devnull }
638 7a4ee46d 2003-11-23 devnull
639 7a4ee46d 2003-11-23 devnull /*
640 7a4ee46d 2003-11-23 devnull * must be called with arena locked
641 24998851 2004-03-11 devnull *
642 24998851 2004-03-11 devnull * cache turned off now that dcache does write caching too.
643 7a4ee46d 2003-11-23 devnull */
644 7a4ee46d 2003-11-23 devnull int
645 7a4ee46d 2003-11-23 devnull flushciblocks(Arena *arena)
646 7a4ee46d 2003-11-23 devnull {
647 7a4ee46d 2003-11-23 devnull int ok;
648 7a4ee46d 2003-11-23 devnull
649 7a4ee46d 2003-11-23 devnull if(arena->cib.data == nil)
650 7a4ee46d 2003-11-23 devnull return 0;
651 7a4ee46d 2003-11-23 devnull qlock(&stats.lock);
652 7a4ee46d 2003-11-23 devnull stats.ciwrites++;
653 7a4ee46d 2003-11-23 devnull qunlock(&stats.lock);
654 24998851 2004-03-11 devnull // ok = writepart(arena->part, arena->base + arena->size - (arena->cib.block + 1) * arena->blocksize, arena->cib.data->data, arena->blocksize);
655 24998851 2004-03-11 devnull ok = 0;
656 7a4ee46d 2003-11-23 devnull if(ok < 0)
657 7a4ee46d 2003-11-23 devnull seterr(EAdmin, "failed writing arena directory block");
658 7a4ee46d 2003-11-23 devnull putdblock(arena->cib.data);
659 7a4ee46d 2003-11-23 devnull arena->cib.data = nil;
660 7a4ee46d 2003-11-23 devnull return ok;
661 7a4ee46d 2003-11-23 devnull }