diff options
Diffstat (limited to 'src/cmd/venti/arenas.c')
-rw-r--r-- | src/cmd/venti/arenas.c | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/src/cmd/venti/arenas.c b/src/cmd/venti/arenas.c deleted file mode 100644 index 5275b938..00000000 --- a/src/cmd/venti/arenas.c +++ /dev/null @@ -1,404 +0,0 @@ -#include "stdinc.h" -#include "dat.h" -#include "fns.h" - -typedef struct AHash AHash; - -/* - * hash table for finding arena's based on their names. - */ -struct AHash -{ - AHash *next; - Arena *arena; -}; - -enum -{ - AHashSize = 512 -}; - -static AHash *ahash[AHashSize]; - -static u32int -hashstr(char *s) -{ - u32int h; - int c; - - h = 0; - for(; c = *s; s++){ - c ^= c << 6; - h += (c << 11) ^ (c >> 1); - c = *s; - h ^= (c << 14) + (c << 7) + (c << 4) + c; - } - return h; -} - -int -addarena(Arena *arena) -{ - AHash *a; - u32int h; - - h = hashstr(arena->name) & (AHashSize - 1); - a = MK(AHash); - if(a == nil) - return -1; - a->arena = arena; - a->next = ahash[h]; - ahash[h] = a; - return 0; -} - -Arena* -findarena(char *name) -{ - AHash *a; - u32int h; - - h = hashstr(name) & (AHashSize - 1); - for(a = ahash[h]; a != nil; a = a->next) - if(strcmp(a->arena->name, name) == 0) - return a->arena; - return nil; -} - -int -delarena(Arena *arena) -{ - AHash *a, *last; - u32int h; - - h = hashstr(arena->name) & (AHashSize - 1); - last = nil; - for(a = ahash[h]; a != nil; a = a->next){ - if(a->arena == arena){ - if(last != nil) - last->next = a->next; - else - ahash[h] = a->next; - free(a); - return 0; - } - last = a; - } - return -1; -} - -ArenaPart* -initarenapart(Part *part) -{ - AMapN amn; - ArenaPart *ap; - ZBlock *b; - u32int i; - int ok; - - b = alloczblock(HeadSize, 0); - if(b == nil || readpart(part, PartBlank, b->data, HeadSize) < 0){ - seterr(EAdmin, "can't read arena partition header: %r"); - return nil; - } - - ap = MKZ(ArenaPart); - if(ap == nil){ - freezblock(b); - return nil; - } - ap->part = part; - ok = unpackarenapart(ap, b->data); - freezblock(b); - if(ok < 0){ - seterr(ECorrupt, "corrupted arena partition header: %r"); - freearenapart(ap, 0); - return nil; - } - - ap->tabbase = (PartBlank + HeadSize + ap->blocksize - 1) & ~(ap->blocksize - 1); - if(ap->version != ArenaPartVersion){ - seterr(ECorrupt, "unknown arena partition version %d", ap->version); - freearenapart(ap, 0); - return nil; - } - if(ap->blocksize & (ap->blocksize - 1)){ - seterr(ECorrupt, "illegal non-power-of-2 block size %d\n", ap->blocksize); - freearenapart(ap, 0); - return nil; - } - if(ap->tabbase >= ap->arenabase){ - seterr(ECorrupt, "arena partition table overlaps with arena storage"); - freearenapart(ap, 0); - return nil; - } - ap->tabsize = ap->arenabase - ap->tabbase; - partblocksize(part, ap->blocksize); - ap->size = ap->part->size & ~(u64int)(ap->blocksize - 1); - - if(readarenamap(&amn, part, ap->tabbase, ap->tabsize) < 0){ - freearenapart(ap, 0); - return nil; - } - ap->narenas = amn.n; - ap->map = amn.map; - if(okamap(ap->map, ap->narenas, ap->arenabase, ap->size, "arena table") < 0){ - freearenapart(ap, 0); - return nil; - } - - ap->arenas = MKNZ(Arena*, ap->narenas); - for(i = 0; i < ap->narenas; i++){ - ap->arenas[i] = initarena(part, ap->map[i].start, ap->map[i].stop - ap->map[i].start, ap->blocksize); - if(ap->arenas[i] == nil){ - freearenapart(ap, 1); - return nil; - } - if(namecmp(ap->map[i].name, ap->arenas[i]->name) != 0){ - seterr(ECorrupt, "arena name mismatches with expected name: %s vs. %s", - ap->map[i].name, ap->arenas[i]->name); - freearenapart(ap, 1); - return nil; - } - if(findarena(ap->arenas[i]->name)){ - seterr(ECorrupt, "duplicate arena name %s in %s", - ap->map[i].name, ap->part->name); - freearenapart(ap, 1); - return nil; - } - } - - for(i = 0; i < ap->narenas; i++) - addarena(ap->arenas[i]); - - return ap; -} - -ArenaPart* -newarenapart(Part *part, u32int blocksize, u32int tabsize) -{ - ArenaPart *ap; - - if(blocksize & (blocksize - 1)){ - seterr(ECorrupt, "illegal non-power-of-2 block size %d\n", blocksize); - return nil; - } - ap = MKZ(ArenaPart); - if(ap == nil) - return nil; - - ap->version = ArenaPartVersion; - ap->part = part; - ap->blocksize = blocksize; - partblocksize(part, blocksize); - ap->size = part->size & ~(u64int)(blocksize - 1); - ap->tabbase = (PartBlank + HeadSize + blocksize - 1) & ~(blocksize - 1); - ap->arenabase = (ap->tabbase + tabsize + blocksize - 1) & ~(blocksize - 1); - ap->tabsize = ap->arenabase - ap->tabbase; - ap->narenas = 0; - - if(wbarenapart(ap) < 0){ - freearenapart(ap, 0); - return nil; - } - - return ap; -} - -int -wbarenapart(ArenaPart *ap) -{ - ZBlock *b; - - if(okamap(ap->map, ap->narenas, ap->arenabase, ap->size, "arena table") < 0) - return -1; - b = alloczblock(HeadSize, 1); - if(b == nil) -//ZZZ set error message? - return -1; - - if(packarenapart(ap, b->data) < 0){ - seterr(ECorrupt, "can't make arena partition header: %r"); - freezblock(b); - return -1; - } - if(writepart(ap->part, PartBlank, b->data, HeadSize) < 0){ - seterr(EAdmin, "can't write arena partition header: %r"); - freezblock(b); - return -1; - } - freezblock(b); - - return wbarenamap(ap->map, ap->narenas, ap->part, ap->tabbase, ap->tabsize); -} - -void -freearenapart(ArenaPart *ap, int freearenas) -{ - int i; - - if(ap == nil) - return; - if(freearenas){ - for(i = 0; i < ap->narenas; i++){ - if(ap->arenas[i] == nil) - continue; - delarena(ap->arenas[i]); - freearena(ap->arenas[i]); - } - } - free(ap->map); - free(ap->arenas); - free(ap); -} - -int -okamap(AMap *am, int n, u64int start, u64int stop, char *what) -{ - u64int last; - u32int i; - - last = start; - for(i = 0; i < n; i++){ - if(am[i].start < last){ - if(i == 0) - seterr(ECorrupt, "invalid start address in %s", what); - else - seterr(ECorrupt, "overlapping ranges in %s", what); - return -1; - } - if(am[i].stop < am[i].start){ - seterr(ECorrupt, "invalid range in %s", what); - return -1; - } - last = am[i].stop; - } - if(last > stop){ - seterr(ECorrupt, "invalid ending address in %s", what); - return -1; - } - return 0; -} - -int -maparenas(AMap *am, Arena **arenas, int n, char *what) -{ - u32int i; - - for(i = 0; i < n; i++){ - arenas[i] = findarena(am[i].name); - if(arenas[i] == nil){ - seterr(EAdmin, "can't find arena '%s' for '%s'\n", am[i].name, what); - return -1; - } - } - return 0; -} - -int -readarenamap(AMapN *amn, Part *part, u64int base, u32int size) -{ - IFile f; - u32int ok; - - if(partifile(&f, part, base, size) < 0) - return -1; - ok = parseamap(&f, amn); - freeifile(&f); - return ok; -} - -int -wbarenamap(AMap *am, int n, Part *part, u64int base, u64int size) -{ - Fmt f; - ZBlock *b; - - b = alloczblock(size, 1); - if(b == nil) - return -1; - - fmtzbinit(&f, b); - - if(outputamap(&f, am, n) < 0){ - seterr(ECorrupt, "arena set size too small"); - freezblock(b); - return -1; - } - if(writepart(part, base, b->data, size) < 0){ - seterr(EAdmin, "can't write arena set: %r"); - freezblock(b); - return -1; - } - freezblock(b); - return 0; -} - -/* - * amap: n '\n' amapelem * n - * n: u32int - * amapelem: name '\t' astart '\t' asize '\n' - * astart, asize: u64int - */ -int -parseamap(IFile *f, AMapN *amn) -{ - AMap *am; - u64int v64; - u32int v; - char *s, *flds[4]; - int i, n; - - /* - * arenas - */ - if(ifileu32int(f, &v) < 0){ - seterr(ECorrupt, "syntax error: bad number of elements in %s", f->name); - return -1; - } - n = v; - if(n > MaxAMap){ - seterr(ECorrupt, "illegal number of elements in %s", f->name); - return -1; - } - am = MKNZ(AMap, n); - if(am == nil) - return -1; - for(i = 0; i < n; i++){ - s = ifileline(f); - if(s == nil || getfields(s, flds, 4, 0, "\t") != 3) - return -1; - if(nameok(flds[0]) < 0) - return -1; - namecp(am[i].name, flds[0]); - if(stru64int(flds[1], &v64) < 0){ - seterr(ECorrupt, "syntax error: bad arena base address in %s", f->name); - free(am); - return -1; - } - am[i].start = v64; - if(stru64int(flds[2], &v64) < 0){ - seterr(ECorrupt, "syntax error: bad arena size in %s", f->name); - free(am); - return -1; - } - am[i].stop = v64; - } - - amn->map = am; - amn->n = n; - return 0; -} - -int -outputamap(Fmt *f, AMap *am, int n) -{ - int i; - - if(fmtprint(f, "%ud\n", n) < 0) - return -1; - for(i = 0; i < n; i++) - if(fmtprint(f, "%s\t%llud\t%llud\n", am[i].name, am[i].start, am[i].stop) < 0) - return -1; - return 0; -} |