| #include "stdinc.h" |
| #include "dat.h" |
| #include "fns.h" |
| |
| void |
| usage(void) |
| { |
| fprint(2, "usage: fmtarenas [-4Z] [-a arenasize] [-b blocksize] name file\n"); |
| threadexitsall(0); |
| } |
| |
| void |
| threadmain(int argc, char *argv[]) |
| { |
| int vers; |
| ArenaPart *ap; |
| Part *part; |
| Arena *arena; |
| u64int addr, limit, asize, apsize; |
| char *file, *name, aname[ANameSize]; |
| int i, n, blocksize, tabsize, zero; |
| |
| ventifmtinstall(); |
| statsinit(); |
| |
| blocksize = 8 * 1024; |
| asize = 512 * 1024 *1024; |
| tabsize = 512 * 1024; /* BUG: should be determine from number of arenas */ |
| zero = -1; |
| vers = ArenaVersion5; |
| ARGBEGIN{ |
| case 'D': |
| settrace(EARGF(usage())); |
| break; |
| case 'a': |
| asize = unittoull(EARGF(usage())); |
| if(asize == TWID64) |
| usage(); |
| break; |
| case 'b': |
| blocksize = unittoull(EARGF(usage())); |
| if(blocksize == ~0) |
| usage(); |
| if(blocksize > MaxDiskBlock){ |
| fprint(2, "block size too large, max %d\n", MaxDiskBlock); |
| threadexitsall("usage"); |
| } |
| break; |
| case '4': |
| vers = ArenaVersion4; |
| break; |
| case 'Z': |
| zero = 0; |
| break; |
| default: |
| usage(); |
| break; |
| }ARGEND |
| |
| if(zero == -1){ |
| if(vers == ArenaVersion4) |
| zero = 1; |
| else |
| zero = 0; |
| } |
| |
| if(argc != 2) |
| usage(); |
| |
| name = argv[0]; |
| file = argv[1]; |
| |
| if(nameok(name) < 0) |
| sysfatal("illegal name template %s", name); |
| |
| part = initpart(file, ORDWR|ODIRECT); |
| if(part == nil) |
| sysfatal("can't open partition %s: %r", file); |
| |
| if(zero) |
| zeropart(part, blocksize); |
| |
| maxblocksize = blocksize; |
| initdcache(20*blocksize); |
| |
| ap = newarenapart(part, blocksize, tabsize); |
| if(ap == nil) |
| sysfatal("can't initialize arena: %r"); |
| |
| apsize = ap->size - ap->arenabase; |
| n = apsize / asize; |
| if(apsize - (n * asize) >= MinArenaSize) |
| n++; |
| |
| fprint(2, "fmtarenas %s: %,d arenas, %,lld bytes storage, %,d bytes for index map\n", |
| file, n, apsize, ap->tabsize); |
| |
| ap->narenas = n; |
| ap->map = MKNZ(AMap, n); |
| ap->arenas = MKNZ(Arena*, n); |
| |
| addr = ap->arenabase; |
| for(i = 0; i < n; i++){ |
| limit = addr + asize; |
| if(limit >= ap->size || ap->size - limit < MinArenaSize){ |
| limit = ap->size; |
| if(limit - addr < MinArenaSize) |
| sysfatal("bad arena set math: runt arena at %lld,%lld %lld", addr, limit, ap->size); |
| } |
| |
| snprint(aname, ANameSize, "%s%d", name, i); |
| |
| if(0) fprint(2, "adding arena %s at [%lld,%lld)\n", aname, addr, limit); |
| |
| arena = newarena(part, vers, aname, addr, limit - addr, blocksize); |
| if(!arena) |
| fprint(2, "can't make new arena %s: %r", aname); |
| freearena(arena); |
| |
| ap->map[i].start = addr; |
| ap->map[i].stop = limit; |
| namecp(ap->map[i].name, aname); |
| |
| addr = limit; |
| } |
| |
| if(wbarenapart(ap) < 0) |
| fprint(2, "can't write back arena partition header for %s: %r\n", file); |
| |
| flushdcache(); |
| threadexitsall(0); |
| } |