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"
5 7a4ee46d 2003-11-23 devnull typedef struct AHash AHash;
8 7a4ee46d 2003-11-23 devnull * hash table for finding arena's based on their names.
10 7a4ee46d 2003-11-23 devnull struct AHash
12 7a4ee46d 2003-11-23 devnull AHash *next;
13 7a4ee46d 2003-11-23 devnull Arena *arena;
18 7a4ee46d 2003-11-23 devnull AHashSize = 512
21 7a4ee46d 2003-11-23 devnull static AHash *ahash[AHashSize];
23 7a4ee46d 2003-11-23 devnull static u32int
24 7a4ee46d 2003-11-23 devnull hashstr(char *s)
26 7a4ee46d 2003-11-23 devnull u32int h;
30 7a4ee46d 2003-11-23 devnull for(; c = *s; s++){
31 7a4ee46d 2003-11-23 devnull c ^= c << 6;
32 7a4ee46d 2003-11-23 devnull h += (c << 11) ^ (c >> 1);
34 7a4ee46d 2003-11-23 devnull h ^= (c << 14) + (c << 7) + (c << 4) + c;
36 7a4ee46d 2003-11-23 devnull return h;
40 7a4ee46d 2003-11-23 devnull addarena(Arena *arena)
42 7a4ee46d 2003-11-23 devnull AHash *a;
43 7a4ee46d 2003-11-23 devnull u32int h;
45 7a4ee46d 2003-11-23 devnull h = hashstr(arena->name) & (AHashSize - 1);
46 7a4ee46d 2003-11-23 devnull a = MK(AHash);
47 7a4ee46d 2003-11-23 devnull if(a == nil)
48 7a4ee46d 2003-11-23 devnull return -1;
49 7a4ee46d 2003-11-23 devnull a->arena = arena;
50 7a4ee46d 2003-11-23 devnull a->next = ahash[h];
51 7a4ee46d 2003-11-23 devnull ahash[h] = a;
52 7a4ee46d 2003-11-23 devnull return 0;
56 7a4ee46d 2003-11-23 devnull findarena(char *name)
58 7a4ee46d 2003-11-23 devnull AHash *a;
59 7a4ee46d 2003-11-23 devnull u32int h;
61 7a4ee46d 2003-11-23 devnull h = hashstr(name) & (AHashSize - 1);
62 7a4ee46d 2003-11-23 devnull for(a = ahash[h]; a != nil; a = a->next)
63 7a4ee46d 2003-11-23 devnull if(strcmp(a->arena->name, name) == 0)
64 7a4ee46d 2003-11-23 devnull return a->arena;
65 7a4ee46d 2003-11-23 devnull return nil;
69 7a4ee46d 2003-11-23 devnull delarena(Arena *arena)
71 7a4ee46d 2003-11-23 devnull AHash *a, *last;
72 7a4ee46d 2003-11-23 devnull u32int h;
74 7a4ee46d 2003-11-23 devnull h = hashstr(arena->name) & (AHashSize - 1);
75 7a4ee46d 2003-11-23 devnull last = nil;
76 7a4ee46d 2003-11-23 devnull for(a = ahash[h]; a != nil; a = a->next){
77 7a4ee46d 2003-11-23 devnull if(a->arena == arena){
78 7a4ee46d 2003-11-23 devnull if(last != nil)
79 7a4ee46d 2003-11-23 devnull last->next = a->next;
81 7a4ee46d 2003-11-23 devnull ahash[h] = a->next;
83 7a4ee46d 2003-11-23 devnull return 0;
85 7a4ee46d 2003-11-23 devnull last = a;
87 7a4ee46d 2003-11-23 devnull return -1;
90 7a4ee46d 2003-11-23 devnull ArenaPart*
91 7a4ee46d 2003-11-23 devnull initarenapart(Part *part)
93 7a4ee46d 2003-11-23 devnull AMapN amn;
94 7a4ee46d 2003-11-23 devnull ArenaPart *ap;
95 7a4ee46d 2003-11-23 devnull ZBlock *b;
96 7a4ee46d 2003-11-23 devnull u32int i;
99 7a4ee46d 2003-11-23 devnull b = alloczblock(HeadSize, 0);
100 7a4ee46d 2003-11-23 devnull if(b == nil || readpart(part, PartBlank, b->data, HeadSize) < 0){
101 7a4ee46d 2003-11-23 devnull seterr(EAdmin, "can't read arena partition header: %r");
102 7a4ee46d 2003-11-23 devnull return nil;
105 7a4ee46d 2003-11-23 devnull ap = MKZ(ArenaPart);
106 7a4ee46d 2003-11-23 devnull if(ap == nil){
107 7a4ee46d 2003-11-23 devnull freezblock(b);
108 7a4ee46d 2003-11-23 devnull return nil;
110 7a4ee46d 2003-11-23 devnull ap->part = part;
111 7a4ee46d 2003-11-23 devnull ok = unpackarenapart(ap, b->data);
112 7a4ee46d 2003-11-23 devnull freezblock(b);
113 7a4ee46d 2003-11-23 devnull if(ok < 0){
114 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "corrupted arena partition header: %r");
115 7a4ee46d 2003-11-23 devnull freearenapart(ap, 0);
116 7a4ee46d 2003-11-23 devnull return nil;
119 7a4ee46d 2003-11-23 devnull ap->tabbase = (PartBlank + HeadSize + ap->blocksize - 1) & ~(ap->blocksize - 1);
120 7a4ee46d 2003-11-23 devnull if(ap->version != ArenaPartVersion){
121 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "unknown arena partition version %d", ap->version);
122 7a4ee46d 2003-11-23 devnull freearenapart(ap, 0);
123 7a4ee46d 2003-11-23 devnull return nil;
125 7a4ee46d 2003-11-23 devnull if(ap->blocksize & (ap->blocksize - 1)){
126 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "illegal non-power-of-2 block size %d\n", ap->blocksize);
127 7a4ee46d 2003-11-23 devnull freearenapart(ap, 0);
128 7a4ee46d 2003-11-23 devnull return nil;
130 7a4ee46d 2003-11-23 devnull if(ap->tabbase >= ap->arenabase){
131 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "arena partition table overlaps with arena storage");
132 7a4ee46d 2003-11-23 devnull freearenapart(ap, 0);
133 7a4ee46d 2003-11-23 devnull return nil;
135 7a4ee46d 2003-11-23 devnull ap->tabsize = ap->arenabase - ap->tabbase;
136 7a4ee46d 2003-11-23 devnull partblocksize(part, ap->blocksize);
137 7a4ee46d 2003-11-23 devnull ap->size = ap->part->size & ~(u64int)(ap->blocksize - 1);
139 7a4ee46d 2003-11-23 devnull if(readarenamap(&amn, part, ap->tabbase, ap->tabsize) < 0){
140 7a4ee46d 2003-11-23 devnull freearenapart(ap, 0);
141 7a4ee46d 2003-11-23 devnull return nil;
143 7a4ee46d 2003-11-23 devnull ap->narenas = amn.n;
144 7a4ee46d 2003-11-23 devnull ap->map = amn.map;
145 7a4ee46d 2003-11-23 devnull if(okamap(ap->map, ap->narenas, ap->arenabase, ap->size, "arena table") < 0){
146 7a4ee46d 2003-11-23 devnull freearenapart(ap, 0);
147 7a4ee46d 2003-11-23 devnull return nil;
150 7a4ee46d 2003-11-23 devnull ap->arenas = MKNZ(Arena*, ap->narenas);
151 7a4ee46d 2003-11-23 devnull for(i = 0; i < ap->narenas; i++){
152 7a4ee46d 2003-11-23 devnull ap->arenas[i] = initarena(part, ap->map[i].start, ap->map[i].stop - ap->map[i].start, ap->blocksize);
153 7a4ee46d 2003-11-23 devnull if(ap->arenas[i] == nil){
154 7a4ee46d 2003-11-23 devnull freearenapart(ap, 1);
155 7a4ee46d 2003-11-23 devnull return nil;
157 7a4ee46d 2003-11-23 devnull if(namecmp(ap->map[i].name, ap->arenas[i]->name) != 0){
158 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "arena name mismatches with expected name: %s vs. %s",
159 7a4ee46d 2003-11-23 devnull ap->map[i].name, ap->arenas[i]->name);
160 7a4ee46d 2003-11-23 devnull freearenapart(ap, 1);
161 7a4ee46d 2003-11-23 devnull return nil;
163 7a4ee46d 2003-11-23 devnull if(findarena(ap->arenas[i]->name)){
164 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "duplicate arena name %s in %s",
165 7a4ee46d 2003-11-23 devnull ap->map[i].name, ap->part->name);
166 7a4ee46d 2003-11-23 devnull freearenapart(ap, 1);
167 7a4ee46d 2003-11-23 devnull return nil;
171 7a4ee46d 2003-11-23 devnull for(i = 0; i < ap->narenas; i++)
172 7a4ee46d 2003-11-23 devnull addarena(ap->arenas[i]);
174 7a4ee46d 2003-11-23 devnull return ap;
177 7a4ee46d 2003-11-23 devnull ArenaPart*
178 7a4ee46d 2003-11-23 devnull newarenapart(Part *part, u32int blocksize, u32int tabsize)
180 7a4ee46d 2003-11-23 devnull ArenaPart *ap;
182 7a4ee46d 2003-11-23 devnull if(blocksize & (blocksize - 1)){
183 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "illegal non-power-of-2 block size %d\n", blocksize);
184 7a4ee46d 2003-11-23 devnull return nil;
186 7a4ee46d 2003-11-23 devnull ap = MKZ(ArenaPart);
187 7a4ee46d 2003-11-23 devnull if(ap == nil)
188 7a4ee46d 2003-11-23 devnull return nil;
190 7a4ee46d 2003-11-23 devnull ap->version = ArenaPartVersion;
191 7a4ee46d 2003-11-23 devnull ap->part = part;
192 7a4ee46d 2003-11-23 devnull ap->blocksize = blocksize;
193 7a4ee46d 2003-11-23 devnull partblocksize(part, blocksize);
194 7a4ee46d 2003-11-23 devnull ap->size = part->size & ~(u64int)(blocksize - 1);
195 7a4ee46d 2003-11-23 devnull ap->tabbase = (PartBlank + HeadSize + blocksize - 1) & ~(blocksize - 1);
196 7a4ee46d 2003-11-23 devnull ap->arenabase = (ap->tabbase + tabsize + blocksize - 1) & ~(blocksize - 1);
197 7a4ee46d 2003-11-23 devnull ap->tabsize = ap->arenabase - ap->tabbase;
198 7a4ee46d 2003-11-23 devnull ap->narenas = 0;
200 7a4ee46d 2003-11-23 devnull if(wbarenapart(ap) < 0){
201 7a4ee46d 2003-11-23 devnull freearenapart(ap, 0);
202 7a4ee46d 2003-11-23 devnull return nil;
205 7a4ee46d 2003-11-23 devnull return ap;
209 7a4ee46d 2003-11-23 devnull wbarenapart(ArenaPart *ap)
211 7a4ee46d 2003-11-23 devnull ZBlock *b;
213 7a4ee46d 2003-11-23 devnull if(okamap(ap->map, ap->narenas, ap->arenabase, ap->size, "arena table") < 0)
214 7a4ee46d 2003-11-23 devnull return -1;
215 7a4ee46d 2003-11-23 devnull b = alloczblock(HeadSize, 1);
216 7a4ee46d 2003-11-23 devnull if(b == nil)
217 7a4ee46d 2003-11-23 devnull //ZZZ set error message?
218 7a4ee46d 2003-11-23 devnull return -1;
220 7a4ee46d 2003-11-23 devnull if(packarenapart(ap, b->data) < 0){
221 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "can't make arena partition header: %r");
222 7a4ee46d 2003-11-23 devnull freezblock(b);
223 7a4ee46d 2003-11-23 devnull return -1;
225 7a4ee46d 2003-11-23 devnull if(writepart(ap->part, PartBlank, b->data, HeadSize) < 0){
226 7a4ee46d 2003-11-23 devnull seterr(EAdmin, "can't write arena partition header: %r");
227 7a4ee46d 2003-11-23 devnull freezblock(b);
228 7a4ee46d 2003-11-23 devnull return -1;
230 7a4ee46d 2003-11-23 devnull freezblock(b);
232 7a4ee46d 2003-11-23 devnull return wbarenamap(ap->map, ap->narenas, ap->part, ap->tabbase, ap->tabsize);
236 7a4ee46d 2003-11-23 devnull freearenapart(ArenaPart *ap, int freearenas)
240 7a4ee46d 2003-11-23 devnull if(ap == nil)
242 7a4ee46d 2003-11-23 devnull if(freearenas){
243 7a4ee46d 2003-11-23 devnull for(i = 0; i < ap->narenas; i++){
244 7a4ee46d 2003-11-23 devnull if(ap->arenas[i] == nil)
245 7a4ee46d 2003-11-23 devnull continue;
246 7a4ee46d 2003-11-23 devnull delarena(ap->arenas[i]);
247 7a4ee46d 2003-11-23 devnull freearena(ap->arenas[i]);
250 7a4ee46d 2003-11-23 devnull free(ap->map);
251 7a4ee46d 2003-11-23 devnull free(ap->arenas);
252 7a4ee46d 2003-11-23 devnull free(ap);
256 7a4ee46d 2003-11-23 devnull okamap(AMap *am, int n, u64int start, u64int stop, char *what)
258 7a4ee46d 2003-11-23 devnull u64int last;
259 7a4ee46d 2003-11-23 devnull u32int i;
261 7a4ee46d 2003-11-23 devnull last = start;
262 7a4ee46d 2003-11-23 devnull for(i = 0; i < n; i++){
263 7a4ee46d 2003-11-23 devnull if(am[i].start < last){
264 7a4ee46d 2003-11-23 devnull if(i == 0)
265 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "invalid start address in %s", what);
267 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "overlapping ranges in %s", what);
268 7a4ee46d 2003-11-23 devnull return -1;
270 7a4ee46d 2003-11-23 devnull if(am[i].stop < am[i].start){
271 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "invalid range in %s", what);
272 7a4ee46d 2003-11-23 devnull return -1;
274 7a4ee46d 2003-11-23 devnull last = am[i].stop;
276 7a4ee46d 2003-11-23 devnull if(last > stop){
277 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "invalid ending address in %s", what);
278 7a4ee46d 2003-11-23 devnull return -1;
280 7a4ee46d 2003-11-23 devnull return 0;
284 7a4ee46d 2003-11-23 devnull maparenas(AMap *am, Arena **arenas, int n, char *what)
286 7a4ee46d 2003-11-23 devnull u32int i;
288 7a4ee46d 2003-11-23 devnull for(i = 0; i < n; i++){
289 7a4ee46d 2003-11-23 devnull arenas[i] = findarena(am[i].name);
290 7a4ee46d 2003-11-23 devnull if(arenas[i] == nil){
291 7a4ee46d 2003-11-23 devnull seterr(EAdmin, "can't find arena '%s' for '%s'\n", am[i].name, what);
292 7a4ee46d 2003-11-23 devnull return -1;
295 7a4ee46d 2003-11-23 devnull return 0;
299 7a4ee46d 2003-11-23 devnull readarenamap(AMapN *amn, Part *part, u64int base, u32int size)
301 7a4ee46d 2003-11-23 devnull IFile f;
302 7a4ee46d 2003-11-23 devnull u32int ok;
304 7a4ee46d 2003-11-23 devnull if(partifile(&f, part, base, size) < 0)
305 7a4ee46d 2003-11-23 devnull return -1;
306 7a4ee46d 2003-11-23 devnull ok = parseamap(&f, amn);
307 7a4ee46d 2003-11-23 devnull freeifile(&f);
308 7a4ee46d 2003-11-23 devnull return ok;
312 7a4ee46d 2003-11-23 devnull wbarenamap(AMap *am, int n, Part *part, u64int base, u64int size)
315 7a4ee46d 2003-11-23 devnull ZBlock *b;
317 7a4ee46d 2003-11-23 devnull b = alloczblock(size, 1);
318 7a4ee46d 2003-11-23 devnull if(b == nil)
319 7a4ee46d 2003-11-23 devnull return -1;
321 7a4ee46d 2003-11-23 devnull fmtzbinit(&f, b);
323 7a4ee46d 2003-11-23 devnull if(outputamap(&f, am, n) < 0){
324 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "arena set size too small");
325 7a4ee46d 2003-11-23 devnull freezblock(b);
326 7a4ee46d 2003-11-23 devnull return -1;
328 7a4ee46d 2003-11-23 devnull if(writepart(part, base, b->data, size) < 0){
329 7a4ee46d 2003-11-23 devnull seterr(EAdmin, "can't write arena set: %r");
330 7a4ee46d 2003-11-23 devnull freezblock(b);
331 7a4ee46d 2003-11-23 devnull return -1;
333 7a4ee46d 2003-11-23 devnull freezblock(b);
334 7a4ee46d 2003-11-23 devnull return 0;
338 7a4ee46d 2003-11-23 devnull * amap: n '\n' amapelem * n
339 7a4ee46d 2003-11-23 devnull * n: u32int
340 7a4ee46d 2003-11-23 devnull * amapelem: name '\t' astart '\t' asize '\n'
341 7a4ee46d 2003-11-23 devnull * astart, asize: u64int
344 7a4ee46d 2003-11-23 devnull parseamap(IFile *f, AMapN *amn)
346 7a4ee46d 2003-11-23 devnull AMap *am;
347 7a4ee46d 2003-11-23 devnull u64int v64;
348 7a4ee46d 2003-11-23 devnull u32int v;
349 7a4ee46d 2003-11-23 devnull char *s, *flds[4];
350 7a4ee46d 2003-11-23 devnull int i, n;
353 7a4ee46d 2003-11-23 devnull * arenas
355 7a4ee46d 2003-11-23 devnull if(ifileu32int(f, &v) < 0){
356 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "syntax error: bad number of elements in %s", f->name);
357 7a4ee46d 2003-11-23 devnull return -1;
360 7a4ee46d 2003-11-23 devnull if(n > MaxAMap){
361 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "illegal number of elements in %s", f->name);
362 7a4ee46d 2003-11-23 devnull return -1;
364 7a4ee46d 2003-11-23 devnull am = MKNZ(AMap, n);
365 7a4ee46d 2003-11-23 devnull if(am == nil)
366 7a4ee46d 2003-11-23 devnull return -1;
367 7a4ee46d 2003-11-23 devnull for(i = 0; i < n; i++){
368 7a4ee46d 2003-11-23 devnull s = ifileline(f);
369 7a4ee46d 2003-11-23 devnull if(s == nil || getfields(s, flds, 4, 0, "\t") != 3)
370 7a4ee46d 2003-11-23 devnull return -1;
371 7a4ee46d 2003-11-23 devnull if(nameok(flds[0]) < 0)
372 7a4ee46d 2003-11-23 devnull return -1;
373 7a4ee46d 2003-11-23 devnull namecp(am[i].name, flds[0]);
374 7a4ee46d 2003-11-23 devnull if(stru64int(flds[1], &v64) < 0){
375 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "syntax error: bad arena base address in %s", f->name);
376 7a4ee46d 2003-11-23 devnull free(am);
377 7a4ee46d 2003-11-23 devnull return -1;
379 7a4ee46d 2003-11-23 devnull am[i].start = v64;
380 7a4ee46d 2003-11-23 devnull if(stru64int(flds[2], &v64) < 0){
381 7a4ee46d 2003-11-23 devnull seterr(ECorrupt, "syntax error: bad arena size in %s", f->name);
382 7a4ee46d 2003-11-23 devnull free(am);
383 7a4ee46d 2003-11-23 devnull return -1;
385 7a4ee46d 2003-11-23 devnull am[i].stop = v64;
388 7a4ee46d 2003-11-23 devnull amn->map = am;
389 7a4ee46d 2003-11-23 devnull amn->n = n;
390 7a4ee46d 2003-11-23 devnull return 0;
394 7a4ee46d 2003-11-23 devnull outputamap(Fmt *f, AMap *am, int n)
398 7a4ee46d 2003-11-23 devnull if(fmtprint(f, "%ud\n", n) < 0)
399 7a4ee46d 2003-11-23 devnull return -1;
400 7a4ee46d 2003-11-23 devnull for(i = 0; i < n; i++)
401 7a4ee46d 2003-11-23 devnull if(fmtprint(f, "%s\t%llud\t%llud\n", am[i].name, am[i].start, am[i].stop) < 0)
402 7a4ee46d 2003-11-23 devnull return -1;
403 7a4ee46d 2003-11-23 devnull return 0;