diff options
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/venti/srv/arena.c | 1 | ||||
-rw-r--r-- | src/cmd/venti/srv/conv.c | 26 | ||||
-rw-r--r-- | src/cmd/venti/srv/icache.c | 2 | ||||
-rw-r--r-- | src/cmd/venti/srv/reseal.c | 81 |
4 files changed, 63 insertions, 47 deletions
diff --git a/src/cmd/venti/srv/arena.c b/src/cmd/venti/srv/arena.c index 1a75c695..d77e0ccf 100644 --- a/src/cmd/venti/srv/arena.c +++ b/src/cmd/venti/srv/arena.c @@ -308,6 +308,7 @@ writeaclump(Arena *arena, Clump *c, u8int *clbuf) if(!arena->memstats.sealed){ logerr(EOk, "seal memstats %s", arena->name); arena->memstats.sealed = 1; + wbarena(arena); } qunlock(&arena->lock); return TWID64; diff --git a/src/cmd/venti/srv/conv.c b/src/cmd/venti/srv/conv.c index f72511b1..29b8c5f0 100644 --- a/src/cmd/venti/srv/conv.c +++ b/src/cmd/venti/srv/conv.c @@ -177,6 +177,27 @@ unpackarena(Arena *arena, u8int *buf) p += U64Size; arena->memstats.sealed = U8GET(p); p += U8Size; + + /* + * 2008/4/2 + * Packarena (below) used to have a bug in which it would + * not zero out any existing extension fields when writing + * the arena metadata. This would manifest itself as arenas + * with arena->diskstats.sealed == 1 but arena->memstats.sealed == 0 + * after a server restart. Because arena->memstats.sealed wouldn't + * be set, the server might try to fit another block into the arena + * (and succeed), violating the append-only structure of the log + * and invalidating any already-computed seal on the arena. + * + * It might end up that other fields in arena->memstats end up + * behind arena->diskstats too, but that would be considerably + * more rare, and the bug is fixed now. The case we need to + * handle is just the sealed mismatch. + * + * If we encounter such a bogus arena, fix the sealed field. + */ + if(arena->diskstats.sealed) + arena->memstats.sealed = 1; }else arena->memstats = arena->diskstats; if(buf + sz != p) @@ -262,6 +283,11 @@ _packarena(Arena *arena, u8int *buf, int forceext) p += U64Size; U8PUT(p, arena->memstats.sealed); p += U8Size; + }else{ + /* Clear any extension fields already on disk. */ + memset(p, 0, ArenaSize5a - ArenaSize5); + p += ArenaSize5a - ArenaSize5; + sz += ArenaSize5a - ArenaSize5; } if(buf + sz != p) diff --git a/src/cmd/venti/srv/icache.c b/src/cmd/venti/srv/icache.c index 5875406b..bf61612c 100644 --- a/src/cmd/venti/srv/icache.c +++ b/src/cmd/venti/srv/icache.c @@ -497,7 +497,7 @@ icachedirty(u32int lo, u32int hi, u64int limit) trace(TraceProc, "icachedirty enter"); qlock(&icache.lock); for(ie = icache.dirty.next; ie != &icache.dirty; ie=ie->next){ - if(ie->state == IEDirty && ie->ia.addr < limit){ + if(ie->state == IEDirty && ie->ia.addr <= limit){ h = hashbits(ie->score, 32); if(lo <= h && h <= hi){ ie->nextdirty = dirty; diff --git a/src/cmd/venti/srv/reseal.c b/src/cmd/venti/srv/reseal.c index 144e640f..f7353122 100644 --- a/src/cmd/venti/srv/reseal.c +++ b/src/cmd/venti/srv/reseal.c @@ -2,28 +2,29 @@ #include "dat.h" #include "fns.h" -static int verbose; -static int fd; static uchar *data; static uchar *data1; static int blocksize; static int sleepms; +static int fd; +static int force; +static vlong offset0; void usage(void) { - fprint(2, "usage: reseal [-b blocksize] [-s ms] [-v] arenapart1 [name...]]\n"); + fprint(2, "usage: reseal [-f] [-b blocksize] [-s ms] arenapart1 [name...]]\n"); threadexitsall(0); } static int -pwriteblock(int fd, uchar *buf, int n, vlong off) +pwriteblock(uchar *buf, int n, vlong off) { int nr, m; for(nr = 0; nr < n; nr += m){ m = n - nr; - m = pwrite(fd, &buf[nr], m, off+nr); + m = pwrite(fd, &buf[nr], m, offset0+off+nr); if(m <= 0) return -1; } @@ -31,30 +32,13 @@ pwriteblock(int fd, uchar *buf, int n, vlong off) } static int -preadblock(int fd, uchar *buf, int n, vlong off) -{ - int nr, m; - - for(nr = 0; nr < n; nr += m){ - m = n - nr; - m = pread(fd, &buf[nr], m, off+nr); - if(m <= 0){ - if(m == 0) - werrstr("early eof"); - return -1; - } - } - return 0; -} - -static int -readblock(int fd, uchar *buf, int n) +preadblock(uchar *buf, int n, vlong off) { int nr, m; for(nr = 0; nr < n; nr += m){ m = n - nr; - m = read(fd, &buf[nr], m); + m = pread(fd, &buf[nr], m, offset0+off+nr); if(m <= 0){ if(m == 0) werrstr("early eof"); @@ -65,9 +49,9 @@ readblock(int fd, uchar *buf, int n) } static int -loadheader(char *name, ArenaHead *head, Arena *arena, int fd, vlong off) +loadheader(char *name, ArenaHead *head, Arena *arena, vlong off) { - if(preadblock(fd, data, head->blocksize, off + head->size - head->blocksize) < 0){ + if(preadblock(data, head->blocksize, off + head->size - head->blocksize) < 0){ fprint(2, "%s: reading arena tail: %r\n", name); return -1; } @@ -90,7 +74,7 @@ loadheader(char *name, ArenaHead *head, Arena *arena, int fd, vlong off) uchar zero[VtScoreSize]; static int -verify(int fd, Arena *arena, void *data, uchar *newscore) +verify(Arena *arena, void *data, uchar *newscore) { vlong e, bs, n, o; DigestState ds, ds1; @@ -105,7 +89,7 @@ verify(int fd, Arena *arena, void *data, uchar *newscore) bs = arena->blocksize; memset(&ds, 0, sizeof ds); for(n = 0; n < e; n += bs){ - if(preadblock(fd, data, bs, o + n) < 0){ + if(preadblock(data, bs, o + n) < 0){ werrstr("read: %r"); return -1; } @@ -115,7 +99,7 @@ verify(int fd, Arena *arena, void *data, uchar *newscore) } /* last block */ - if(preadblock(fd, data, arena->blocksize, o + e) < 0){ + if(preadblock(data, arena->blocksize, o + e) < 0){ werrstr("read: %r"); return -1; } @@ -123,8 +107,11 @@ verify(int fd, Arena *arena, void *data, uchar *newscore) sha1(data, bs - VtScoreSize, nil, &ds); sha1(zero, VtScoreSize, score, &ds); if(scorecmp(score, arena->score) != 0){ - werrstr("score mismatch: %V != %V", score, arena->score); - return -1; + if(!force){ + werrstr("score mismatch: %V != %V", score, arena->score); + return -1; + } + fprint(2, "warning: score mismatch %V != %V\n", score, arena->score); } /* prepare new last block */ @@ -154,7 +141,7 @@ resealarena(char *name, vlong len) /* * read a little bit, which will include the header */ - if(preadblock(fd, data, HeadSize, off) < 0){ + if(preadblock(data, HeadSize, off) < 0){ fprint(2, "%s: reading header: %r\n", name); return; } @@ -169,7 +156,7 @@ resealarena(char *name, vlong len) if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0) fprint(2, "%s: warning: unexpected name %s\n", name, head.name); - if(loadheader(name, &head, &arena, fd, off) < 0) + if(loadheader(name, &head, &arena, off) < 0) return; if(!arena.diskstats.sealed){ @@ -177,20 +164,19 @@ resealarena(char *name, vlong len) return; } - if(verify(fd, &arena, data, newscore) < 0){ + if(verify(&arena, data, newscore) < 0){ fprint(2, "%s: failed to verify before reseal: %r\n", name); return; } - fprint(2, "%s: verified: %V\n", name, arena.score); - if(pwriteblock(fd, data, arena.blocksize, arena.base + arena.size) < 0){ + if(pwriteblock(data, arena.blocksize, arena.base + arena.size) < 0){ fprint(2, "%s: writing new tail: %r\n", name); return; } scorecp(arena.score, newscore); fprint(2, "%s: resealed: %V\n", name, newscore); - if(verify(fd, &arena, data, newscore) < 0){ + if(verify(&arena, data, newscore) < 0){ fprint(2, "%s: failed to verify after reseal!: %r\n", name); return; } @@ -216,11 +202,11 @@ shouldcheck(char *name, char **s, int n) } char * -readap(int fd, ArenaPart *ap) +readap(ArenaPart *ap) { char *table; - if(preadblock(fd, data, 8192, PartBlank) < 0) + if(preadblock(data, 8192, PartBlank) < 0) sysfatal("read arena part header: %r"); if(unpackarenapart(ap, data) < 0) sysfatal("corrupted arena part header: %r"); @@ -229,7 +215,7 @@ readap(int fd, ArenaPart *ap) ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1); ap->tabsize = ap->arenabase - ap->tabbase; table = malloc(ap->tabsize+1); - if(preadblock(fd, (uchar*)table, ap->tabsize, ap->tabbase) < 0) + if(preadblock((uchar*)table, ap->tabsize, ap->tabbase) < 0) sysfatal("reading arena part directory: %r"); table[ap->tabsize] = 0; return table; @@ -242,6 +228,7 @@ threadmain(int argc, char *argv[]) char *p, *q, *table, *f[10], line[256]; vlong start, stop; ArenaPart ap; + Part *part; ventifmtinstall(); blocksize = MaxIoSize; @@ -249,12 +236,12 @@ threadmain(int argc, char *argv[]) case 'b': blocksize = unittoull(EARGF(usage())); break; + case 'f': + force = 1; + break; case 's': sleepms = atoi(EARGF(usage())); break; - case 'v': - verbose++; - break; default: usage(); break; @@ -264,10 +251,12 @@ threadmain(int argc, char *argv[]) usage(); data = vtmalloc(blocksize); - if((fd = open(argv[0], ORDWR)) < 0) - sysfatal("open %s: %r", argv[0]); + if((part = initpart(argv[0], ORDWR)) == nil) + sysfatal("open partition %s: %r", argv[0]); + fd = part->fd; + offset0 = part->offset; - table = readap(fd, &ap); + table = readap(&ap); nline = atoi(table); p = strchr(table, '\n'); |