commit 75d048884cfcb7cc4404b384da50923e22224365 from: Russ Cox date: Mon May 25 09:11:27 2009 UTC venti: 32-bit extensions to data structures commit - 33b446b8bbfea80552d462296d27ad4114fbd3fb commit + 75d048884cfcb7cc4404b384da50923e22224365 blob - 14627dcb724791420fdc97e45b4b2caf23309d1a blob + 3365182faeee915425e19ecd0087166329ea21a0 --- include/venti.h +++ include/venti.h @@ -86,7 +86,6 @@ enum { VtScoreSize = 20, VtMaxStringSize = 1024, - VtMaxLumpSize = 56*1024, VtPointerDepth = 7 }; #define VtMaxFileSize ((1ULL<<48)-1) @@ -137,7 +136,8 @@ enum _VtEntryDir = 1<<1, /* a directory */ _VtEntryDepthShift = 2, /* shift for pointer depth */ _VtEntryDepthMask = 7<<2, /* mask for pointer depth */ - VtEntryLocal = 1<<5 /* for local storage only */ + VtEntryLocal = 1<<5, /* for local storage only */ + _VtEntryBig = 1<<6, }; enum { @@ -146,8 +146,8 @@ enum struct VtEntry { ulong gen; /* generation number */ - ushort psize; /* pointer block size */ - ushort dsize; /* data block size */ + ulong psize; /* pointer block size */ + ulong dsize; /* data block size */ uchar type; uchar flags; uvlong size; @@ -162,14 +162,15 @@ struct VtRoot char name[128]; char type[128]; uchar score[VtScoreSize]; /* to a Dir block */ - ushort blocksize; /* maximum block size */ + ulong blocksize; /* maximum block size */ uchar prev[VtScoreSize]; /* last root block */ }; enum { VtRootSize = 300, - VtRootVersion = 2 + VtRootVersion = 2, + _VtRootVersionBig = 1<<15, }; void vtrootpack(VtRoot*, uchar*); @@ -394,7 +395,8 @@ struct VtBlock uchar *data; uchar score[VtScoreSize]; - uchar type; /* BtXXX */ + uchar type; /* VtXXX */ + ulong size; /* internal to cache */ int nlock; @@ -412,14 +414,13 @@ struct VtBlock u32int vtglobaltolocal(uchar[VtScoreSize]); void vtlocaltoglobal(u32int, uchar[VtScoreSize]); -VtCache *vtcachealloc(VtConn*, int blocksize, ulong nblocks); +VtCache *vtcachealloc(VtConn*, ulong maxmem); void vtcachefree(VtCache*); VtBlock *vtcachelocal(VtCache*, u32int addr, int type); -VtBlock *vtcacheglobal(VtCache*, uchar[VtScoreSize], int type); -VtBlock *vtcacheallocblock(VtCache*, int type); +VtBlock *vtcacheglobal(VtCache*, uchar[VtScoreSize], int type, ulong size); +VtBlock *vtcacheallocblock(VtCache*, int type, ulong size); void vtcachesetwrite(VtCache*, int(*)(VtConn*,uchar[VtScoreSize],uint,uchar*,int)); void vtblockput(VtBlock*); -u32int vtcacheblocksize(VtCache*); int vtblockwrite(VtBlock*); VtBlock *vtblockcopy(VtBlock*); void vtblockduplock(VtBlock*); @@ -438,6 +439,7 @@ struct VtFile int local; VtBlock *b; /* block containing this file */ uchar score[VtScoreSize]; /* score of block containing this file */ + int bsize; /* size of block */ /* immutable */ VtCache *c; blob - faa558f3df96ea9d8aff6b39bb11c77a5f293eb4 blob + bf17ea3806ca25ab7cc57e26fa1b058a2ebbf26c --- src/cmd/vac/file.c +++ src/cmd/vac/file.c @@ -1730,7 +1730,7 @@ Err1: static char EBadVacFormat[] = "bad format for vac file"; static VacFs * -vacfsalloc(VtConn *z, int bsize, int ncache, int mode) +vacfsalloc(VtConn *z, int bsize, ulong cachemem, int mode) { VacFs *fs; @@ -1738,7 +1738,7 @@ vacfsalloc(VtConn *z, int bsize, int ncache, int mode) fs->z = z; fs->bsize = bsize; fs->mode = mode; - fs->cache = vtcachealloc(z, bsize, ncache); + fs->cache = vtcachealloc(z, cachemem); return fs; } @@ -1767,7 +1767,7 @@ readscore(int fd, uchar score[VtScoreSize]) } VacFs* -vacfsopen(VtConn *z, char *file, int mode, int ncache) +vacfsopen(VtConn *z, char *file, int mode, ulong cachemem) { int fd; uchar score[VtScoreSize]; @@ -1788,11 +1788,11 @@ vacfsopen(VtConn *z, char *file, int mode, int ncache) } close(fd); } - return vacfsopenscore(z, score, mode, ncache); + return vacfsopenscore(z, score, mode, cachemem); } VacFs* -vacfsopenscore(VtConn *z, u8int *score, int mode, int ncache) +vacfsopenscore(VtConn *z, u8int *score, int mode, ulong cachemem) { VacFs *fs; int n; @@ -1818,13 +1818,19 @@ vacfsopenscore(VtConn *z, u8int *score, int mode, int return nil; } - fs = vacfsalloc(z, rt.blocksize, ncache, mode); + fs = vacfsalloc(z, rt.blocksize, cachemem, mode); memmove(fs->score, score, VtScoreSize); fs->mode = mode; memmove(e.score, rt.score, VtScoreSize); e.gen = 0; + + // Don't waste cache memory on directories + // when rt.blocksize is large. e.psize = (rt.blocksize/VtEntrySize)*VtEntrySize; + if(e.psize > 60000) + e.psize = (60000/VtEntrySize)*VtEntrySize; + e.dsize = rt.blocksize; e.type = VtDirType; e.flags = VtEntryActive; @@ -1925,7 +1931,7 @@ vacfsclose(VacFs *fs) * Create a fresh vac fs. */ VacFs * -vacfscreate(VtConn *z, int bsize, int ncache) +vacfscreate(VtConn *z, int bsize, ulong cachemem) { VacFs *fs; VtFile *f; @@ -1937,18 +1943,24 @@ vacfscreate(VtConn *z, int bsize, int ncache) MetaEntry me; int psize; - if((fs = vacfsalloc(z, bsize, ncache, VtORDWR)) == nil) + if((fs = vacfsalloc(z, bsize, cachemem, VtORDWR)) == nil) return nil; - + /* * Fake up an empty vac fs. */ psize = bsize/VtEntrySize*VtEntrySize; + if(psize > 60000) + psize = 60000/VtEntrySize*VtEntrySize; +fprint(2, "create bsize %d psize %d\n", bsize, psize); + f = vtfilecreateroot(fs->cache, psize, bsize, VtDirType); + if(f == nil) + sysfatal("vtfilecreateroot: %r"); vtfilelock(f, VtORDWR); - + /* Write metablock containing root directory VacDir. */ - b = vtcacheallocblock(fs->cache, VtDataType); + b = vtcacheallocblock(fs->cache, VtDataType, bsize); mbinit(&mb, b->data, bsize, bsize/BytesPerEntry); memset(&vd, 0, sizeof vd); vd.elem = "/"; blob - 9777464f6e2139c5ebf1ec5a09b9d7bb14baf279 blob + 5555cc0eb287595d50c381434f9c36c3ad132496 --- src/cmd/vac/pack.c +++ src/cmd/vac/pack.c @@ -77,7 +77,7 @@ mbunpack(MetaBlock *mb, uchar *p, int n) magic = U32GET(p); if(magic != MetaMagic && magic != MetaMagic+1) { - werrstr("bad meta block magic"); + werrstr("bad meta block magic %#08ux", magic); return -1; } mb->size = U16GET(p+4); blob - ab799cb0a9b79a31f283b2cc9a1821cc8fb52643 blob + 8b2b290dbfcd66453423db069a0b62f9a80cb161 --- src/cmd/vac/unvac.c +++ src/cmd/vac/unvac.c @@ -94,7 +94,7 @@ threadmain(int argc, char *argv[]) if(vtconnect(conn) < 0) sysfatal("vtconnect: %r"); - fs = vacfsopen(conn, argv[0], VtOREAD, 128); + fs = vacfsopen(conn, argv[0], VtOREAD, 4<<20); if(fs == nil) sysfatal("vacfsopen: %r"); blob - d6c17b4b808274fe151a9f5f66258c5f3fc176ad blob + bf5118b46b296343227ba76acbce0119224923cf --- src/cmd/vac/vac.c +++ src/cmd/vac/vac.c @@ -100,8 +100,6 @@ threadmain(int argc, char **argv) u = unittoull(EARGF(usage())); if(u < 512) u = 512; - if(u > VtMaxLumpSize) - u = VtMaxLumpSize; blocksize = u; break; case 'd': @@ -170,10 +168,10 @@ threadmain(int argc, char **argv) if((outfd = create(archivefile, OWRITE, 0666)) < 0) sysfatal("create %s: %r", archivefile); atexit(removevacfile); // because it is new - if((fs = vacfscreate(z, blocksize, 512)) == nil) + if((fs = vacfscreate(z, blocksize, 4<<20)) == nil) sysfatal("vacfscreate: %r"); }else{ - if((fs = vacfsopen(z, archivefile, VtORDWR, 512)) == nil) + if((fs = vacfsopen(z, archivefile, VtORDWR, 4<<20)) == nil) sysfatal("vacfsopen %s: %r", archivefile); if((fdiff = recentarchive(fs, oldpath)) != nil){ if(verbose) @@ -213,7 +211,7 @@ threadmain(int argc, char **argv) else if((outfd = create(vacfile, OWRITE, 0666)) < 0) sysfatal("create %s: %r", vacfile); atexit(removevacfile); - if((fs = vacfscreate(z, blocksize, 512)) == nil) + if((fs = vacfscreate(z, blocksize, 4<<20)) == nil) sysfatal("vacfscreate: %r"); f = vacfsgetroot(fs); @@ -450,7 +448,7 @@ void vac(VacFile *fp, VacFile *diffp, char *name, Dir *d) { char *elem, *s; - static char buf[65536]; + static char *buf; int fd, i, n, bsize; vlong off; Dir *dk; // kids @@ -541,6 +539,8 @@ vac(VacFile *fp, VacFile *diffp, char *name, Dir *d) }else{ off = 0; bsize = fs->bsize; + if(buf == nil) + buf = vtmallocz(bsize); if(fdiff){ /* * Copy fdiff's contents into f by moving the score. @@ -708,7 +708,7 @@ vacmerge(VacFile *fp, char *name) if(strlen(name) < 4 || strcmp(name+strlen(name)-4, ".vac") != 0) return -1; - if((mfs = vacfsopen(z, name, VtOREAD, 100)) == nil) + if((mfs = vacfsopen(z, name, VtOREAD, 4<<20)) == nil) return -1; if(verbose) fprint(2, "merging %s\n", name); blob - cb599a9c3c1b81a9ce6cae086343a6cd35dd4879 blob + 0edd41e40bf5b7b126863825f0dfec50f197f5c5 --- src/cmd/vac/vac.h +++ src/cmd/vac/vac.h @@ -97,9 +97,9 @@ struct VacFs VtCache *cache; }; -VacFs *vacfsopen(VtConn *z, char *file, int mode, int ncache); -VacFs *vacfsopenscore(VtConn *z, u8int *score, int mode, int ncache); -VacFs *vacfscreate(VtConn *z, int bsize, int ncache); +VacFs *vacfsopen(VtConn *z, char *file, int mode, ulong cachemem); +VacFs *vacfsopenscore(VtConn *z, u8int *score, int mode, ulong cachemem); +VacFs *vacfscreate(VtConn *z, int bsize, ulong cachemem); void vacfsclose(VacFs *fs); int vacfssync(VacFs *fs); int vacfssnapshot(VacFs *fs, char *src, char *dst); blob - 5c65cf3b05086e9731982b17c99ccafefcfa29f2 blob + ad72098f65131ec95d3c2df5641d7f115de88851 --- src/cmd/vac/vacfs.c +++ src/cmd/vac/vacfs.c @@ -118,6 +118,31 @@ notifyf(void *a, char *s) noted(NDFLT); } +#define TWID64 ~(u64int)0 +static u64int +unittoull(char *s) +{ + char *es; + u64int n; + + if(s == nil) + return TWID64; + n = strtoul(s, &es, 0); + if(*es == 'k' || *es == 'K'){ + n *= 1024; + es++; + }else if(*es == 'm' || *es == 'M'){ + n *= 1024*1024; + es++; + }else if(*es == 'g' || *es == 'G'){ + n *= 1024*1024*1024; + es++; + } + if(*es != '\0') + return TWID64; + return n; +} + void threadmain(int argc, char *argv[]) { @@ -125,10 +150,10 @@ threadmain(int argc, char *argv[]) int p[2], fd; int stdio; char *host = nil; - long ncache; + ulong mem; + mem = 16<<20; stdio = 0; - ncache = 256; fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); @@ -140,9 +165,6 @@ threadmain(int argc, char *argv[]) fmtinstall('F', fcallfmt); dflag = 1; break; - case 'c': - ncache = atoi(EARGF(usage())); - break; case 'i': defmnt = nil; stdio = 1; @@ -157,6 +179,9 @@ threadmain(int argc, char *argv[]) break; case 's': defsrv = "vacfs"; + break; + case 'M': + mem = unittoull(EARGF(usage())); break; case 'm': defmnt = EARGF(usage()); @@ -206,7 +231,7 @@ threadmain(int argc, char *argv[]) if(vtconnect(conn) < 0) sysfatal("vtconnect: %r"); - fs = vacfsopen(conn, argv[0], VtOREAD, ncache); + fs = vacfsopen(conn, argv[0], VtOREAD, mem); if(fs == nil) sysfatal("vacfsopen: %r"); blob - 7e03b56c3556301a8aa77ff297e9b5bf9d6b35c6 blob + 4a05e0537fe8200299c93eabc76acfee0969fd3c --- src/cmd/venti/copy.c +++ src/cmd/venti/copy.c @@ -4,6 +4,12 @@ #include #include +enum +{ + // XXX What to do here? + VtMaxLumpSize = 65536, +}; + int changes; int rewrite; int ignoreerrors; blob - 8481303a6fe49ce5122dc256d77481b929e7ae47 blob + c148b8668ff61f9e84be379d5f85ac8da1d29c6c --- src/cmd/venti/dump.c +++ src/cmd/venti/dump.c @@ -5,6 +5,12 @@ #include #include +enum +{ + // XXX What to do here? + VtMaxLumpSize = 65536, +}; + VtConn *z; char *host; blob - a48e62e6a9c6183f6e252b65655367f1fa06dd48 blob + 4883c1d7b5a1b943b93bf9bd1901e36298480bc6 --- src/cmd/venti/read.c +++ src/cmd/venti/read.c @@ -4,6 +4,12 @@ #include #include +enum +{ + // XXX What to do here? + VtMaxLumpSize = 65536, +}; + void usage(void) { blob - 5d67ad316f1e66696d87fd3e9b5f54ec2821582d blob + d41d44bc56a991c1ffdceac42fab7fa489f29b7e --- src/cmd/venti/root.c +++ src/cmd/venti/root.c @@ -38,7 +38,7 @@ threadmain(int argc, char *argv[]) if(argc == 0) usage(); - buf = vtmallocz(VtMaxLumpSize); + buf = vtmallocz(8192); z = vtdial(host); if(z == nil) @@ -52,7 +52,7 @@ threadmain(int argc, char *argv[]) fprint(2, "cannot parse score '%s': %r\n", argv[i]); continue; } - n = vtread(z, score, VtRootType, buf, VtMaxLumpSize); + n = vtread(z, score, VtRootType, buf, 8192); if(n < 0){ fprint(2, "could not read block %V: %r\n", score); continue; blob - b0b942b8177f21e5a45b8d7c6de231b8038320dd blob + 7b2bf49d701ec14541c865bd68043c48f24de871 --- src/cmd/venti/srv/dat.h +++ src/cmd/venti/srv/dat.h @@ -37,6 +37,12 @@ typedef struct Bloom Bloom; enum { + /* + * formerly fundamental constant, + * now a server-imposed limitation. + */ + VtMaxLumpSize = 56*1024, + ABlockLog = 9, /* log2(512), the quantum for reading arenas */ ANameSize = 64, MaxDiskBlock = 64*1024, /* max. allowed size for a disk block */ blob - c11a5a3143a22947b55bbd2f1e00974ce56b1afa blob + d627cae7c40abc7cd507227309644351de8ab2d9 --- src/cmd/venti/write.c +++ src/cmd/venti/write.c @@ -4,6 +4,12 @@ #include #include +enum +{ + // XXX What to do here? + VtMaxLumpSize = 65536, +}; + void usage(void) { blob - 4830439c404d3356b1cc25938b62d2e6bae9623b blob + e3e4420457907e66e7928e0449ccc086d56e4049 --- src/libdiskfs/venti.c +++ src/libdiskfs/venti.c @@ -96,13 +96,13 @@ _vtfileblock(VtCache *c, VtEntry *e, u32int bn) } /*fprint(2, "vtread %V\n", e->score); */ - b = vtcacheglobal(c, e->score, e->type); + b = vtcacheglobal(c, e->score, e->type, d == 0 ? e->dsize : e->psize); for(i=d-1; i>=0 && b; i--){ t = VtDataType+i; /*fprint(2, "vtread %V\n", b->data+index[i]*VtScoreSize); */ memmove(score, b->data+index[i]*VtScoreSize, VtScoreSize); vtblockput(b); - b = vtcacheglobal(c, score, t); + b = vtcacheglobal(c, score, t, i == 0 ? e->dsize : e->psize); } return b; } @@ -122,7 +122,7 @@ diskopenventi(VtCache *c, uchar score[VtScoreSize]) VtRoot root; VtBlock *b; - if((b = vtcacheglobal(c, score, VtRootType)) == nil) + if((b = vtcacheglobal(c, score, VtRootType, VtRootSize)) == nil) goto Err; if(vtrootunpack(&root, b->data) < 0) goto Err; @@ -132,7 +132,7 @@ diskopenventi(VtCache *c, uchar score[VtScoreSize]) } vtblockput(b); - if((b = vtcacheglobal(c, root.score, VtDirType)) == nil) + if((b = vtcacheglobal(c, root.score, VtDirType, VtEntrySize)) == nil) goto Err; if(vtentryunpack(&e, b->data, 0) < 0) goto Err; blob - 636a6ea781b6249cbab7fe5c5f4717bbd8df4d73 blob + 030efb0a608e6a9ee52f101d59ba3f2d34fbde99 --- src/libventi/cache.c +++ src/libventi/cache.c @@ -32,7 +32,6 @@ struct VtCache { QLock lk; VtConn *z; - u32int blocksize; u32int now; /* ticks for usage time stamps */ VtBlock **hash; /* hash table for finding addresses */ int nhash; @@ -40,41 +39,45 @@ struct VtCache int nheap; VtBlock *block; /* all allocated blocks */ int nblock; - uchar *mem; /* memory for all blocks and data */ int (*write)(VtConn*, uchar[VtScoreSize], uint, uchar*, int); + VtBlock *dead; /* blocks we don't have memory for */ + ulong mem; + ulong maxmem; }; static void cachecheck(VtCache*); VtCache* -vtcachealloc(VtConn *z, int blocksize, ulong nblock) +vtcachealloc(VtConn *z, ulong maxmem) { - uchar *p; VtCache *c; int i; + int nblock; VtBlock *b; + ulong maxmem0; + maxmem0 = maxmem; c = vtmallocz(sizeof(VtCache)); - + nblock = maxmem/100/(sizeof(VtBlock)+2*sizeof(VtBlock*)); c->z = z; - c->blocksize = (blocksize + 127) & ~127; c->nblock = nblock; c->nhash = nblock; c->hash = vtmallocz(nblock*sizeof(VtBlock*)); c->heap = vtmallocz(nblock*sizeof(VtBlock*)); c->block = vtmallocz(nblock*sizeof(VtBlock)); - c->mem = vtmallocz(nblock*c->blocksize); c->write = vtwrite; + maxmem -= nblock*(sizeof(VtBlock) + 2*sizeof(VtBlock*)); + maxmem -= sizeof(VtCache); + if((long)maxmem < 0) + sysfatal("cache size far too small: %lud", maxmem0); + c->mem = maxmem; - p = c->mem; for(i=0; iblock[i]; b->addr = NilBlock; b->c = c; - b->data = p; b->heap = i; c->heap[i] = b; - p += c->blocksize; } c->nheap = nblock; cachecheck(c); @@ -102,13 +105,14 @@ vtcachefree(VtCache *c) qlock(&c->lk); cachecheck(c); - for(i=0; inblock; i++) + for(i=0; inblock; i++) { assert(c->block[i].ref == 0); + vtfree(c->block[i].data); + } vtfree(c->hash); vtfree(c->heap); vtfree(c->block); - vtfree(c->mem); vtfree(c); } @@ -128,11 +132,10 @@ vtcachedump(VtCache *c) static void cachecheck(VtCache *c) { - u32int size, now; + u32int now; int i, k, refed; VtBlock *b; - size = c->blocksize; now = c->now; for(i = 0; i < c->nheap; i++){ @@ -151,8 +154,6 @@ cachecheck(VtCache *c) refed = 0; for(i = 0; i < c->nblock; i++){ b = &c->block[i]; - if(b->data != &c->mem[i * size]) - sysfatal("mis-blocked at %d", i); if(b->ref && b->heap == BadHeap) refed++; else if(b->addr != NilBlock) @@ -295,6 +296,57 @@ if(0)fprint(2, "droping %x:%V\n", b->addr, b->score); /* set vtBlock to a reasonable state */ b->ref = 1; b->iostate = BioEmpty; + return b; +} + +/* + * evict blocks until there is enough memory for size bytes. + */ +static VtBlock* +vtcacheevict(VtCache *c, ulong size) +{ + VtBlock *b; + + /* + * If we were out of memory and put some blocks + * to the side but now we have memory, grab one. + */ + if(c->mem >= size && c->dead) { + b = c->dead; + c->dead = b->next; + b->next = nil; + goto alloc; + } + + /* + * Otherwise, evict until we have memory. + */ + for(;;) { + b = vtcachebumpblock(c); + if(c->mem+b->size >= size) + break; + /* + * chain b onto dead list + */ + free(b->data); + b->data = nil; + c->mem += b->size; + b->size = 0; + b->next = c->dead; + c->dead = b; + } + + /* + * Allocate memory for block. + */ +alloc: + if(size > b->size || size <= b->size/2) { + free(b->data); + c->mem += b->size; + c->mem -= size; + b->size = size; + b->data = vtmalloc(size); + } return b; } @@ -332,16 +384,16 @@ vtcachelocal(VtCache *c, u32int addr, int type) } VtBlock* -vtcacheallocblock(VtCache *c, int type) +vtcacheallocblock(VtCache *c, int type, ulong size) { VtBlock *b; qlock(&c->lk); - b = vtcachebumpblock(c); + b = vtcacheevict(c, size); b->iostate = BioLocal; b->type = type; b->addr = (b - c->block)+1; - vtzeroextend(type, b->data, 0, c->blocksize); + vtzeroextend(type, b->data, 0, size); vtlocaltoglobal(b->addr, b->score); qunlock(&c->lk); @@ -356,7 +408,7 @@ vtcacheallocblock(VtCache *c, int type) * if it's not there, load it, bumping some other block. */ VtBlock* -vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type) +vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type, ulong size) { VtBlock *b; ulong h; @@ -409,7 +461,7 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], in /* * not found */ - b = vtcachebumpblock(c); + b = vtcacheevict(c, size); b->addr = NilBlock; b->type = type; memmove(b->score, score, VtScoreSize); @@ -435,7 +487,7 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], in qunlock(&c->lk); vtcachenread++; - n = vtread(c->z, score, type, b->data, c->blocksize); + n = vtread(c->z, score, type, b->data, size); if(n < 0){ if(chattyventi) fprint(2, "read %V: %r\n", score); @@ -445,7 +497,7 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], in vtblockput(b); return nil; } - vtzeroextend(type, b->data, n, c->blocksize); + vtzeroextend(type, b->data, n, size); b->iostate = BioVenti; b->nlock = 1; if(vttracelevel) @@ -534,7 +586,7 @@ vtblockwrite(VtBlock *b) } c = b->c; - n = vtzerotruncate(b->type, b->data, c->blocksize); + n = vtzerotruncate(b->type, b->data, b->size); vtcachenwrite++; if(c->write(c->z, score, b->type, b->data, n) < 0) return -1; @@ -554,24 +606,18 @@ vtblockwrite(VtBlock *b) return 0; } -uint -vtcacheblocksize(VtCache *c) -{ - return c->blocksize; -} - VtBlock* vtblockcopy(VtBlock *b) { VtBlock *bb; vtcachencopy++; - bb = vtcacheallocblock(b->c, b->type); + bb = vtcacheallocblock(b->c, b->type, b->size); if(bb == nil){ vtblockput(b); return nil; } - memmove(bb->data, b->data, b->c->blocksize); + memmove(bb->data, b->data, b->size); vtblockput(b); bb->pc = getcallerpc(&b); return bb; blob - aeb8dada34e85b03f6cb5d76dd8495ddeba82b74 blob + 6485714a322038b18a0d4cab1090e820d6c94ef5 --- src/libventi/entry.c +++ src/libventi/entry.c @@ -6,13 +6,37 @@ static int checksize(int n) { - if(n < 256 || n > VtMaxLumpSize) { + if(n < 256) { werrstr("bad block size %#ux", n); return -1; } return 0; } +// _VtEntryBig integer format is floating-point: +// (n>>5) << (n&31). +// Convert this number; must be exact or return -1. +int +vttobig(ulong n) +{ + int shift; + ulong n0; + + n0 = n; + shift = 0; + while(n >= (1<<(16 - 5))) { + if(n & 1) + return -1; + shift++; + n >>= 1; + } + + n = (n<<5) | shift; + if(((n>>5)<<(n&31)) != n0) + sysfatal("vttobig %#lux => %#lux failed", n0, n); + return n; +} + void vtentrypack(VtEntry *e, uchar *p, int index) { @@ -20,21 +44,31 @@ vtentrypack(VtEntry *e, uchar *p, int index) int flags; uchar *op; int depth; + int psize, dsize; p += index * VtEntrySize; op = p; - U32PUT(p, e->gen); - p += 4; - U16PUT(p, e->psize); - p += 2; - U16PUT(p, e->dsize); - p += 2; depth = e->type&VtTypeDepthMask; flags = (e->flags&~(_VtEntryDir|_VtEntryDepthMask)); flags |= depth << _VtEntryDepthShift; if(e->type - depth == VtDirType) flags |= _VtEntryDir; + U32PUT(p, e->gen); + p += 4; + psize = e->psize; + dsize = e->dsize; + if(psize >= (1<<16) || dsize >= (1<<16)) { + flags |= _VtEntryBig; + psize = vttobig(psize); + dsize = vttobig(dsize); + if(psize < 0 || dsize < 0) + sysfatal("invalid entry psize/dsize: %d/%d", e->psize, e->dsize); + } + U16PUT(p, psize); + p += 2; + U16PUT(p, dsize); + p += 2; U8PUT(p, flags); p++; memset(p, 0, 5); @@ -62,10 +96,14 @@ vtentryunpack(VtEntry *e, uchar *p, int index) e->dsize = U16GET(p); p += 2; e->flags = U8GET(p); + p++; + if(e->flags & _VtEntryBig) { + e->psize = (e->psize>>5)<<(e->psize & 31); + e->dsize = (e->dsize>>5)<<(e->dsize & 31); + } e->type = (e->flags&_VtEntryDir) ? VtDirType : VtDataType; e->type += (e->flags & _VtEntryDepthMask) >> _VtEntryDepthShift; - e->flags &= ~(_VtEntryDir|_VtEntryDepthMask); - p++; + e->flags &= ~(_VtEntryDir|_VtEntryDepthMask|_VtEntryBig); p += 5; e->size = U48GET(p); p += 6; blob - 1573a155e0353b3a890413319c1f45d956601542 blob + ebd71998f2fdada5aebbbbb006b85b0a3cfe1e66 --- src/libventi/file.c +++ src/libventi/file.c @@ -36,7 +36,6 @@ static VtFile * vtfilealloc(VtCache *c, VtBlock *b, VtFile *p, u32int offset, int mode) { int epb; - u32int size; VtEntry e; VtFile *r; @@ -74,15 +73,9 @@ vtfilealloc(VtCache *c, VtBlock *b, VtFile *p, u32int return nil; } - size = vtcacheblocksize(c); - if(e.dsize > size || e.psize > size){ - werrstr("block sizes %ud, %ud bigger than cache block size %ud", - e.psize, e.dsize, size); - return nil; - } - r = vtmallocz(sizeof(VtFile)); r->c = c; + r->bsize = b->size; r->mode = mode; r->dsize = e.dsize; r->psize = e.psize; @@ -126,7 +119,7 @@ vtfileopenroot(VtCache *c, VtEntry *e) VtBlock *b; VtFile *f; - b = vtcacheallocblock(c, VtDirType); + b = vtcacheallocblock(c, VtDirType, VtEntrySize); if(b == nil) return nil; @@ -191,8 +184,6 @@ _vtfilecreate(VtFile *r, int o, int psize, int dsize, u32int offset; assert(ISLOCKED(r)); - assert(psize <= VtMaxLumpSize); - assert(dsize <= VtMaxLumpSize); assert(type == VtDirType || type == VtDataType); if(!r->dir){ @@ -325,12 +316,12 @@ vtfilegetsize(VtFile *r) static int shrinksize(VtFile *r, VtEntry *e, uvlong size) { - int i, depth, type, isdir, ppb; + int i, depth, bsiz, type, isdir, ppb; uvlong ptrsz; uchar score[VtScoreSize]; VtBlock *b; - b = vtcacheglobal(r->c, e->score, e->type); + b = vtcacheglobal(r->c, e->score, e->type, r->dsize); if(b == nil) return -1; @@ -369,7 +360,11 @@ shrinksize(VtFile *r, VtEntry *e, uvlong size) type--; memmove(score, b->data+i*VtScoreSize, VtScoreSize); vtblockput(b); - b = vtcacheglobal(r->c, score, type); + if(type == VtDataType || type == VtDirType) + bsiz = r->dsize; + else + bsiz = r->psize; + b = vtcacheglobal(r->c, score, type, bsiz); if(b == nil) return -1; } @@ -498,10 +493,10 @@ vtfilesetentry(VtFile *r, VtEntry *e) } static VtBlock * -blockwalk(VtBlock *p, int index, VtCache *c, int mode, VtEntry *e) +blockwalk(VtFile *r, VtBlock *p, int index, VtCache *c, int mode, VtEntry *e) { VtBlock *b; - int type; + int type, size; uchar *score; VtEntry oe; @@ -519,12 +514,16 @@ blockwalk(VtBlock *p, int index, VtCache *c, int mode, } /*print("walk from %V/%d ty %d to %V ty %d\n", p->score, index, p->type, score, type); */ + if(type == VtDirType || type == VtDataType) + size = r->dsize; + else + size = r->psize; if(mode == VtOWRITE && vtglobaltolocal(score) == NilBlock){ - b = vtcacheallocblock(c, type); + b = vtcacheallocblock(c, type, size); if(b) goto HaveCopy; }else - b = vtcacheglobal(c, score, type); + b = vtcacheglobal(c, score, type, size); if(b == nil || mode == VtOREAD) return b; @@ -566,7 +565,7 @@ growdepth(VtFile *r, VtBlock *p, VtEntry *e, int depth assert(ISLOCKED(r)); assert(depth <= VtPointerDepth); - b = vtcacheglobal(r->c, e->score, e->type); + b = vtcacheglobal(r->c, e->score, e->type, r->dsize); if(b == nil) return -1; @@ -577,7 +576,7 @@ growdepth(VtFile *r, VtBlock *p, VtEntry *e, int depth * or an error occurs. */ while(DEPTH(e->type) < depth){ - bb = vtcacheallocblock(r->c, e->type+1); + bb = vtcacheallocblock(r->c, e->type+1, r->psize); if(bb == nil) break; memmove(bb->data, b->score, VtScoreSize); @@ -605,7 +604,7 @@ shrinkdepth(VtFile *r, VtBlock *p, VtEntry *e, int dep assert(ISLOCKED(r)); assert(depth <= VtPointerDepth); - rb = vtcacheglobal(r->c, e->score, e->type); + rb = vtcacheglobal(r->c, e->score, e->type, r->psize); if(rb == nil) return -1; @@ -618,7 +617,7 @@ shrinkdepth(VtFile *r, VtBlock *p, VtEntry *e, int dep ob = nil; b = rb; for(; DEPTH(e->type) > depth; e->type--){ - nb = vtcacheglobal(r->c, b->data, e->type-1); + nb = vtcacheglobal(r->c, b->data, e->type-1, r->psize); if(nb == nil) break; if(ob!=nil && ob!=rb) @@ -720,7 +719,7 @@ assert(b->type == VtDirType); m = VtORDWR; for(i=DEPTH(e.type); i>=0; i--){ - bb = blockwalk(b, index[i], r->c, i==0 ? mode : m, &e); + bb = blockwalk(r, b, index[i], r->c, i==0 ? mode : m, &e); if(bb == nil) goto Err; vtblockput(b); @@ -768,7 +767,7 @@ vtfileblockscore(VtFile *r, u32int bn, uchar score[VtS index[DEPTH(e.type)] = r->offset % r->epb; for(i=DEPTH(e.type); i>=1; i--){ - bb = blockwalk(b, index[i], r->c, VtOREAD, &e); + bb = blockwalk(r, b, index[i], r->c, VtOREAD, &e); if(bb == nil) goto Err; vtblockput(b); @@ -837,7 +836,7 @@ fileloadblock(VtFile *r, int mode) case VtORDWR: assert(r->mode == VtORDWR); if(r->local == 1){ - b = vtcacheglobal(r->c, r->score, VtDirType); + b = vtcacheglobal(r->c, r->score, VtDirType, r->bsize); if(b == nil) return nil; b->pc = getcallerpc(&r); @@ -861,7 +860,7 @@ fileloadblock(VtFile *r, int mode) } addr = vtglobaltolocal(r->score); if(addr == NilBlock) - return vtcacheglobal(r->c, r->score, VtDirType); + return vtcacheglobal(r->c, r->score, VtDirType, r->bsize); b = vtcachelocal(r->c, addr, VtDirType); if(b) @@ -1220,7 +1219,7 @@ vtfileflushbefore(VtFile *r, u64int offset) */ index[depth] = r->offset % r->epb; for(i=depth; i>=0; i--){ - bb = blockwalk(b, index[i], r->c, VtORDWR, &e); + bb = blockwalk(r, b, index[i], r->c, VtORDWR, &e); if(bb == nil) goto Err; bi[i] = bb; blob - 5b4ccac6ede536bf477fb790371f00f8dbb08442 blob + b1a153d51161427001144770b799bef373a95e89 --- src/libventi/root.c +++ src/libventi/root.c @@ -6,19 +6,30 @@ static int checksize(int n) { - if(n < 256 || n > VtMaxLumpSize) { + if(n < 256) { werrstr("bad block size"); return -1; } return 0; } +extern int vttobig(ulong); + void vtrootpack(VtRoot *r, uchar *p) { uchar *op = p; + int vers, bsize; - U16PUT(p, VtRootVersion); + vers = VtRootVersion; + bsize = r->blocksize; + if(bsize >= (1<<16)) { + vers |= _VtRootVersionBig; + bsize = vttobig(bsize); + if(bsize < 0) + sysfatal("invalid root blocksize: %#x", r->blocksize); + } + U16PUT(p, vers); p += 2; memmove(p, r->name, sizeof(r->name)); p += sizeof(r->name); @@ -26,7 +37,7 @@ vtrootpack(VtRoot *r, uchar *p) p += sizeof(r->type); memmove(p, r->score, VtScoreSize); p += VtScoreSize; - U16PUT(p, r->blocksize); + U16PUT(p, bsize); p += 2; memmove(p, r->prev, VtScoreSize); p += VtScoreSize; @@ -42,7 +53,7 @@ vtrootunpack(VtRoot *r, uchar *p) memset(r, 0, sizeof(*r)); vers = U16GET(p); - if(vers != VtRootVersion) { + if((vers&~_VtRootVersionBig) != VtRootVersion) { werrstr("unknown root version"); return -1; } @@ -56,6 +67,8 @@ vtrootunpack(VtRoot *r, uchar *p) memmove(r->score, p, VtScoreSize); p += VtScoreSize; r->blocksize = U16GET(p); + if(vers & _VtRootVersionBig) + r->blocksize = (r->blocksize >> 5) << (r->blocksize & 31); if(checksize(r->blocksize) < 0) return -1; p += 2;