Blame


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