aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/venti/srv/arena.c1
-rw-r--r--src/cmd/venti/srv/conv.c26
-rw-r--r--src/cmd/venti/srv/icache.c2
-rw-r--r--src/cmd/venti/srv/reseal.c81
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');