use clump info directory to walk past corruption

This commit is contained in:
rsc 2007-05-03 03:14:59 +00:00
parent 0e26338762
commit 703c2d41ac

View file

@ -11,6 +11,7 @@ VtConn *z;
int fast; /* and a bit unsafe; only for benchmarking */ int fast; /* and a bit unsafe; only for benchmarking */
int haveaoffset; int haveaoffset;
int maxwrites = -1; int maxwrites = -1;
int verbose;
typedef struct ZClump ZClump; typedef struct ZClump ZClump;
struct ZClump struct ZClump
@ -38,6 +39,8 @@ vtsendthread(void *v)
break; break;
if(vtwrite(z, zcl.cl.info.score, zcl.cl.info.type, zcl.lump->data, zcl.cl.info.uncsize) < 0) if(vtwrite(z, zcl.cl.info.score, zcl.cl.info.type, zcl.lump->data, zcl.cl.info.uncsize) < 0)
sysfatal("failed writing clump %llud: %r", zcl.aa); sysfatal("failed writing clump %llud: %r", zcl.aa);
if(verbose)
print("%V\n", zcl.cl.info.score);
freezblock(zcl.lump); freezblock(zcl.lump);
} }
/* /*
@ -57,9 +60,10 @@ vtsendthread(void *v)
static void static void
rdarena(Arena *arena, u64int offset) rdarena(Arena *arena, u64int offset)
{ {
int i;
u64int a, aa, e; u64int a, aa, e;
u32int magic;
Clump cl; Clump cl;
ClumpInfo ci;
uchar score[VtScoreSize]; uchar score[VtScoreSize];
ZBlock *lump; ZBlock *lump;
ZClump zcl; ZClump zcl;
@ -71,50 +75,51 @@ rdarena(Arena *arena, u64int offset)
e = arena->base + arena->size; e = arena->base + arena->size;
if(offset != ~(u64int)0) { if(offset != ~(u64int)0) {
if(offset >= e-a) if(offset >= e-a)
sysfatal("bad offset %llud >= %llud\n", sysfatal("bad offset %#llx >= %#llx\n",
offset, e-a); offset, e-a);
aa = offset; aa = offset;
} else } else
aa = 0; aa = 0;
if(maxwrites != 0) if(maxwrites != 0)
for(; aa < e; aa += ClumpSize+cl.info.size) { for(i=0, a=0; i<arena->memstats.clumps; i++, a+=ClumpSize+ci.size) {
magic = clumpmagic(arena, aa); if(readclumpinfo(arena, i, &ci) < 0)
if(magic == ClumpFreeMagic)
break;
if(magic != arena->clumpmagic) {
if(0) fprint(2, "illegal clump magic number %#8.8ux offset %llud\n",
magic, aa);
break; break;
if(a < aa || ci.type == VtCorruptType){
if(ci.type == VtCorruptType)
fprint(2, "corrupt at %#llx: +%d\n", a, ClumpSize+ci.size);
continue;
} }
lump = loadclump(arena, aa, 0, &cl, score, 0); lump = loadclump(arena, a, 0, &cl, score, 0);
if(lump == nil) { if(lump == nil) {
fprint(2, "clump %llud failed to read: %r\n", aa); fprint(2, "clump %#llx failed to read: %r\n", a);
break; continue;
} }
if(!fast && cl.info.type != VtCorruptType) { if(!fast && cl.info.type != VtCorruptType) {
scoremem(score, lump->data, cl.info.uncsize); scoremem(score, lump->data, cl.info.uncsize);
if(scorecmp(cl.info.score, score) != 0) { if(scorecmp(cl.info.score, score) != 0) {
fprint(2, "clump %llud has mismatched score\n", aa); fprint(2, "clump %#llx has mismatched score\n", a);
break; break;
} }
if(vttypevalid(cl.info.type) < 0) { if(vttypevalid(cl.info.type) < 0) {
fprint(2, "clump %llud has bad type %d\n", aa, cl.info.type); fprint(2, "clump %#llx has bad type %d\n", a, cl.info.type);
break; break;
} }
} }
if(z && cl.info.type != VtCorruptType){ if(z && cl.info.type != VtCorruptType){
zcl.cl = cl; zcl.cl = cl;
zcl.lump = lump; zcl.lump = lump;
zcl.aa = aa; zcl.aa = a;
send(c, &zcl); send(c, &zcl);
}else }else
freezblock(lump); freezblock(lump);
if(maxwrites>0 && --maxwrites == 0) if(maxwrites>0 && --maxwrites == 0)
break; break;
} }
if(a > aa)
aa = a;
if(haveaoffset) if(haveaoffset)
print("end offset %llud\n", aa); print("end offset %#llx\n", aa);
} }
void void
@ -147,6 +152,9 @@ threadmain(int argc, char *argv[])
case 'M': case 'M':
maxwrites = atoi(EARGF(usage())); maxwrites = atoi(EARGF(usage()));
break; break;
case 'v':
verbose = 1;
break;
default: default:
usage(); usage();
break; break;
@ -204,8 +212,8 @@ threadmain(int argc, char *argv[])
vtproc(vtsendthread, nil); vtproc(vtsendthread, nil);
rdarena(arena, offset); rdarena(arena, offset);
if(vtsync(z) < 0) if(vtsync(z) < 0)
sysfatal("executing sync: %r"); sysfatal("executing sync: %r");
memset(&zerocl, 0, sizeof zerocl); memset(&zerocl, 0, sizeof zerocl);
for(i=0; i<12; i++) for(i=0; i<12; i++)