/* * read the arena header and trailer blocks from disk */ static int loadarena(Arena *arena) { ArenaHead head; ZBlock *b; b = alloczblock(arena->blocksize, 0, arena->part->blocksize); if(b == nil) return -1; if(readpart(arena->part, arena->base + arena->size, b->data, arena->blocksize) < 0){ freezblock(b); return -1; } if(unpackarena(arena, b->data) < 0){ freezblock(b); return -1; } if(arena->version != ArenaVersion4 && arena->version != ArenaVersion5){ seterr(EAdmin, "unknown arena version %d", arena->version); freezblock(b); return -1; } scorecp(arena->score, &b->data[arena->blocksize - VtScoreSize]); if(readpart(arena->part, arena->base - arena->blocksize, b->data, arena->blocksize) < 0){ logerr(EAdmin, "can't read arena header: %r"); freezblock(b); return 0; } if(unpackarenahead(&head, b->data) < 0) logerr(ECorrupt, "corrupted arena header: %r"); else if(namecmp(arena->name, head.name)!=0 || arena->clumpmagic != head.clumpmagic || arena->version != head.version || arena->blocksize != head.blocksize || arena->size + 2 * arena->blocksize != head.size){ if(namecmp(arena->name, head.name)!=0) logerr(ECorrupt, "arena tail name %s head %s", arena->name, head.name); else if(arena->clumpmagic != head.clumpmagic) logerr(ECorrupt, "arena %d tail clumpmagic 0x%lux head 0x%lux", debugarena, (uint32_t)arena->clumpmagic, (uint32_t)head.clumpmagic); else if(arena->version != head.version) logerr(ECorrupt, "arena tail version %d head version %d", arena->version, head.version); else if(arena->blocksize != head.blocksize) logerr(ECorrupt, "arena tail block size %d head %d", arena->blocksize, head.blocksize); else if(arena->size+2*arena->blocksize != head.size) logerr(ECorrupt, "arena tail size %lud head %lud", (uint32_t)arena->size+2*arena->blocksize, head.size); else logerr(ECorrupt, "arena header inconsistent with arena data"); } freezblock(b); return 0; }
static int diskarenapart(HConnect *c, char *disk, Part *p) { char *arenaname; ArenaPart ap; ArenaHead head; Arena arena; char *table; char *score; char *clump; uchar *blk; vlong start, end, off; char tbuf[60]; hprint(&c->hout, "<h1>arena partition %s</h1>\n", disk); if((table = readap(p, &ap)) == nil){ hprint(&c->hout, "%r\n"); goto out; } hprint(&c->hout, "<pre>\n"); hprint(&c->hout, "version=%d blocksize=%d base=%d\n", ap.version, ap.blocksize, ap.arenabase); hprint(&c->hout, "</pre>\n"); arenaname = hargstr(c, "arena", ""); if(arenaname[0] == 0){ diskarenatable(c, disk, table); goto out; } if(xfindarena(table, arenaname, &start, &end) < 0){ hprint(&c->hout, "no such arena %s\n", arenaname); goto out; } hprint(&c->hout, "<h2>arena %s</h2>\n", arenaname); hprint(&c->hout, "<pre>start=%#llx end=%#llx<pre>\n", start, end); if(end < start || end - start < HeadSize){ hprint(&c->hout, "bad size %#llx\n", end - start); goto out; } // read arena header, tail blk = vtmalloc(HeadSize); if(readpart(p, start, blk, HeadSize) != HeadSize){ hprint(&c->hout, "reading header: %r\n"); vtfree(blk); goto out; } if(unpackarenahead(&head, blk) < 0){ hprint(&c->hout, "corrupt arena header: %r\n"); // hhex(blk, HeadSize); vtfree(blk); goto out; } vtfree(blk); hprint(&c->hout, "head:\n<pre>\n"); hprint(&c->hout, "version=%d name=%s blocksize=%d size=%#llx clumpmagic=%#ux\n", head.version, head.name, head.blocksize, head.size, head.clumpmagic); hprint(&c->hout, "</pre><br><br>\n"); if(head.blocksize > MaxIoSize || head.blocksize >= end - start){ hprint(&c->hout, "corrupt block size %d\n", head.blocksize); goto out; } blk = vtmalloc(head.blocksize); if(readpart(p, end - head.blocksize, blk, head.blocksize) < 0){ hprint(&c->hout, "reading tail: %r\n"); vtfree(blk); goto out; } memset(&arena, 0, sizeof arena); arena.part = p; arena.blocksize = head.blocksize; arena.clumpmax = head.blocksize / ClumpInfoSize; arena.base = start + head.blocksize; arena.size = end - start - 2 * head.blocksize; if(unpackarena(&arena, blk) < 0){ vtfree(blk); goto out; } scorecp(arena.score, blk+head.blocksize - VtScoreSize); vtfree(blk); hprint(&c->hout, "tail:\n<pre>\n"); hprint(&c->hout, "version=%d name=%s\n", arena.version, arena.name); hprint(&c->hout, "ctime=%d %s\n", arena.ctime, fmttime(tbuf, arena.ctime)); hprint(&c->hout, "wtime=%d %s\n", arena.wtime, fmttime(tbuf, arena.wtime)); hprint(&c->hout, "clumpmagic=%#ux\n", arena.clumpmagic); hprint(&c->hout, "score %V\n", arena.score); hprint(&c->hout, "diskstats:\n"); hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n", arena.diskstats.clumps, arena.diskstats.cclumps, arena.diskstats.used, arena.diskstats.uncsize, arena.diskstats.sealed); hprint(&c->hout, "memstats:\n"); hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n", arena.memstats.clumps, arena.memstats.cclumps, arena.memstats.used, arena.memstats.uncsize, arena.memstats.sealed); if(arena.clumpmax == 0){ hprint(&c->hout, "bad clumpmax\n"); goto out; } score = hargstr(c, "score", ""); clump = hargstr(c, "clump", ""); if(clump[0]){ off = strtoull(clump, 0, 0); diskarenaclump(c, &arena, off, score[0] ? score : nil); }else if(score[0]){ diskarenaclump(c, &arena, -1, score); }else{ diskarenatoc(c, &arena); } out: free(table); return 0; }
void threadmain(int argc, char *argv[]) { int i; char *file; Arena *arena; u64int offset, aoffset; Part *part; uchar buf[8192]; ArenaHead head; ZClump zerocl; ventifmtinstall(); qlock(&godot); aoffset = 0; ARGBEGIN{ case 'f': fast = 1; ventidoublechecksha1 = 0; break; case 'h': host = EARGF(usage()); break; case 'o': haveaoffset = 1; aoffset = strtoull(EARGF(usage()), 0, 0); break; case 'M': maxwrites = atoi(EARGF(usage())); break; case 'v': verbose = 1; break; default: usage(); break; }ARGEND offset = ~(u64int)0; switch(argc) { default: usage(); case 2: offset = strtoull(argv[1], 0, 0); /* fall through */ case 1: file = argv[0]; } fmtinstall('V', vtscorefmt); statsinit(); part = initpart(file, OREAD); if(part == nil) sysfatal("can't open file %s: %r", file); if(readpart(part, aoffset, buf, sizeof buf) < 0) sysfatal("can't read file %s: %r", file); if(unpackarenahead(&head, buf) < 0) sysfatal("corrupted arena header: %r"); if(aoffset+head.size > part->size) sysfatal("arena is truncated: want %llud bytes have %llud", head.size, part->size); partblocksize(part, head.blocksize); initdcache(8 * MaxDiskBlock); arena = initarena(part, aoffset, head.size, head.blocksize); if(arena == nil) sysfatal("initarena: %r"); z = nil; if(host==nil || strcmp(host, "/dev/null") != 0){ z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); } c = chancreate(sizeof(ZClump), 0); for(i=0; i<12; i++) vtproc(vtsendthread, nil); rdarena(arena, offset); if(vtsync(z) < 0) sysfatal("executing sync: %r"); memset(&zerocl, 0, sizeof zerocl); for(i=0; i<12; i++) send(c, &zerocl); if(z){ vthangup(z); } threadexitsall(0); }
static void cmparena(char *name, vlong len) { ArenaHead head; DigestState s; u64int n, e; u32int bs; int i, j; char buf[20]; fprint(2, "cmp %s\n", name); memset(&s, 0, sizeof s); /* * read a little bit, which will include the header */ if(readblock(fd, data, HeadSize) < 0){ fprint(2, "%s: reading header: %r\n", name); return; } if(unpackarenahead(&head, data) < 0){ fprint(2, "%s: corrupt arena header: %r\n", name); return; } if(head.version != ArenaVersion4 && head.version != ArenaVersion5) fprint(2, "%s: warning: unknown arena version %d\n", name, head.version); if(len != 0 && len != head.size) fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len); if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0) fprint(2, "%s: warning: unexpected name %s\n", name, head.name); if(readblock(fd1, data1, HeadSize) < 0){ fprint(2, "%s: reading header: %r\n", name); return; } if(unpackarenahead(&head, data) < 0){ fprint(2, "%s: corrupt arena header: %r\n", name); return; } if(head.version != ArenaVersion4 && head.version != ArenaVersion5) fprint(2, "%s: warning: unknown arena version %d\n", name, head.version); if(len != 0 && len != head.size) fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len); if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0) fprint(2, "%s: warning: unexpected name %s\n", name, head.name); seek(fd, -HeadSize, 1); seek(fd1, -HeadSize, 1); if(printheader(name, &head, fd) < 0) return; /* * now we know how much to read * read everything but the last block, which is special */ e = head.size; bs = blocksize; for(n = 0; n < e; n += bs){ if(n + bs > e) bs = e - n; if(readblock(fd, data, bs) < 0){ fprint(2, "%s: read data: %r\n", name); return; } if(readblock(fd1, data1, bs) < 0){ fprint(2, "%s: read data: %r\n", name); return; } if(memcmp(data, data1, bs) != 0){ print("mismatch at %llx\n", n); for(i=0; i<bs; i+=16){ if(memcmp(data+i, data1+i, 16) != 0){ snprint(buf, sizeof buf, "%llx", n+i); print("%s ", buf); for(j=0; j<16; j++){ print(" %.2ux", data[i+j]); if(j == 7) print(" -"); } print("\n"); print("%*s ", (int)strlen(buf), ""); for(j=0; j<16; j++){ print(" %.2ux", data1[i+j]); if(j == 7) print(" -"); } print("\n"); } } } } }