tmerge - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 9f8a101a7c2e88b968741e9057da4f741a736fb5
 (DIR) parent 715d6f8e14e8bc20f21209ca107bef3300d28e8c
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Tue, 15 Apr 2008 19:17:51 -0700
       
       merge
       
       Diffstat:
         M lib/moveplan9.files                 |       2 ++
         M src/cmd/venti/srv/arena.c           |       1 +
         M src/cmd/venti/srv/conv.c            |      26 ++++++++++++++++++++++++++
         M src/cmd/venti/srv/icache.c          |       2 +-
         M src/cmd/venti/srv/reseal.c          |      81 +++++++++++++------------------
       
       5 files changed, 65 insertions(+), 47 deletions(-)
       ---
 (DIR) diff --git a/lib/moveplan9.files b/lib/moveplan9.files
       t@@ -23,6 +23,8 @@ bin/unmount
        bin/vwhois
        bin/vmount
        bin/yesterday
       +mail/lib/qmail
       +mail/lib/remotemail
        man/mkindex
        tmac/tmac.an
        tmac/tmac.anhtml
 (DIR) diff --git a/src/cmd/venti/srv/arena.c b/src/cmd/venti/srv/arena.c
       t@@ -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;
 (DIR) diff --git a/src/cmd/venti/srv/conv.c b/src/cmd/venti/srv/conv.c
       t@@ -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)
       t@@ -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)
 (DIR) diff --git a/src/cmd/venti/srv/icache.c b/src/cmd/venti/srv/icache.c
       t@@ -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;
 (DIR) diff --git a/src/cmd/venti/srv/reseal.c b/src/cmd/venti/srv/reseal.c
       t@@ -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;
                }
       t@@ -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");
       t@@ -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;
                }
       t@@ -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;
       t@@ -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;
                        }
       t@@ -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;
                }
       t@@ -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 */
       t@@ -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;
                }
       t@@ -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){
       t@@ -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;
                }
       t@@ -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");
       t@@ -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;
       t@@ -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;
       t@@ -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;
       t@@ -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');