#include <u.h>#include <libc.h>#include <diskfs.h>#include <venti.h> extern void vtlibthread(void); typedef struct DiskVenti DiskVenti;struct DiskVenti{ Disk disk; VtEntry e; VtCache *c;}; extern int nfilereads;extern void _nfilereads_darwin_sucks(void); /* * This part is like file.c but doesn't require storing the root block * in the cache permanently and doesn't care about locking since * all the blocks are read-only. Perhaps at some point this functionality * should go into libvac in some form. */static intvtfileindices(VtEntry *e, u32int bn, int *index){ int i, np; memset(index, 0, VtPointerDepth*sizeof(int)); np = e->psize/VtScoreSize; memset(index, 0, sizeof(index)); for(i=0; bn > 0; i++){ if(i >= VtPointerDepth){ werrstr("bad block number %lud", (ulong)bn); return -1; } index[i] = bn % np; bn /= np; } return i;} VtBlock *_vtfileblock(VtCache*, VtEntry*, u32int); /* avoid auto-inline by putting later in file */static voiddiskventiblockput(Block *b){ vtblockput(b->priv); free(b);} static Block*diskventiread(Disk *dd, u32int len, u64int offset){ DiskVenti *d = (DiskVenti*)dd; VtBlock *vb; Block *b; int frag; nfilereads++; vb = _vtfileblock(d->c, &d->e, offset/d->e.dsize); if(vb == nil) return nil; b = mallocz(sizeof(Block), 1); if(b == nil){ vtblockput(vb); return nil; } b->priv = vb; b->_close = diskventiblockput; frag = offset%d->e.dsize; b->data = (uchar*)vb->data + frag; b->len = d->e.dsize - frag; if(b->len > len) b->len = len; return b;} VtBlock*_vtfileblock(VtCache *c, VtEntry *e, u32int bn){ VtBlock *b; int i, d, index[VtPointerDepth+1], t; uchar score[VtScoreSize]; i = vtfileindices(e, bn, index); if(i < 0) return nil; d = (e->type&VtTypeDepthMask); if(i > d){ werrstr("bad address %d > %d (%x %x)", i, d, e->type, e->flags); return nil; } /*fprint(2, "vtread %V\n", e->score); */ 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, i == 0 ? e->dsize : e->psize); } return b;} static voiddiskventiclose(Disk *dd){ DiskVenti *d = (DiskVenti*)dd; free(d);} static u64intdiskventisize(Disk *dd){ DiskVenti *d = (DiskVenti*)dd; return d->e.size;} Disk*diskopenventi(VtCache *c, uchar score[VtScoreSize]){ DiskVenti *d; VtEntry e; VtRoot root; VtBlock *b; if((b = vtcacheglobal(c, score, VtRootType, VtRootSize)) == nil) goto Err; if(vtrootunpack(&root, b->data) < 0) goto Err; if(root.blocksize < 512 || (root.blocksize&(root.blocksize-1))){ werrstr("bad blocksize %d", root.blocksize); goto Err; } vtblockput(b); if((b = vtcacheglobal(c, root.score, VtDirType, VtEntrySize)) == nil) goto Err; if(vtentryunpack(&e, b->data, 0) < 0) goto Err; vtblockput(b); b = nil; if((e.type&VtTypeBaseMask) != VtDataType){ werrstr("not a single file"); goto Err; } d = mallocz(sizeof(DiskVenti), 1); if(d == nil) goto Err; d->disk._read = diskventiread; d->disk._close = diskventiclose; d->disk._size = diskventisize; d->e = e; d->c = c; return &d->disk; Err: if(b) vtblockput(b); _nfilereads_darwin_sucks(); /* force Darwin ld to pull in file.o */ return nil;}
#include <u.h>
#include <libc.h>
#include <diskfs.h>
#include <venti.h>
extern void vtlibthread(void);
typedef struct DiskVenti DiskVenti;
struct DiskVenti
{
Disk disk;
VtEntry e;
VtCache *c;
};
extern int nfilereads;
extern void _nfilereads_darwin_sucks(void);
/*
* This part is like file.c but doesn't require storing the root block
* in the cache permanently and doesn't care about locking since
* all the blocks are read-only. Perhaps at some point this functionality
* should go into libvac in some form.
*/
static int
vtfileindices(VtEntry *e, u32int bn, int *index)
{
int i, np;
memset(index, 0, VtPointerDepth*sizeof(int));
np = e->psize/VtScoreSize;
memset(index, 0, sizeof(index));
for(i=0; bn > 0; i++){
if(i >= VtPointerDepth){
werrstr("bad block number %lud", (ulong)bn);
return -1;
}
index[i] = bn % np;
bn /= np;
}
return i;
}
VtBlock *_vtfileblock(VtCache*, VtEntry*, u32int); /* avoid auto-inline by putting later in file */
static void
diskventiblockput(Block *b)
{
vtblockput(b->priv);
free(b);
}
static Block*
diskventiread(Disk *dd, u32int len, u64int offset)
{
DiskVenti *d = (DiskVenti*)dd;
VtBlock *vb;
Block *b;
int frag;
nfilereads++;
vb = _vtfileblock(d->c, &d->e, offset/d->e.dsize);
if(vb == nil)
return nil;
b = mallocz(sizeof(Block), 1);
if(b == nil){
vtblockput(vb);
return nil;
}
b->priv = vb;
b->_close = diskventiblockput;
frag = offset%d->e.dsize;
b->data = (uchar*)vb->data + frag;
b->len = d->e.dsize - frag;
if(b->len > len)
b->len = len;
return b;
}
VtBlock*
_vtfileblock(VtCache *c, VtEntry *e, u32int bn)
{
VtBlock *b;
int i, d, index[VtPointerDepth+1], t;
uchar score[VtScoreSize];
i = vtfileindices(e, bn, index);
if(i < 0)
return nil;
d = (e->type&VtTypeDepthMask);
if(i > d){
werrstr("bad address %d > %d (%x %x)", i, d, e->type, e->flags);
return nil;
}
/*fprint(2, "vtread %V\n", e->score); */
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, i == 0 ? e->dsize : e->psize);
}
return b;
}
static void
diskventiclose(Disk *dd)
{
DiskVenti *d = (DiskVenti*)dd;
free(d);
}
static u64int
diskventisize(Disk *dd)
{
DiskVenti *d = (DiskVenti*)dd;
return d->e.size;
}
Disk*
diskopenventi(VtCache *c, uchar score[VtScoreSize])
{
DiskVenti *d;
VtEntry e;
VtRoot root;
VtBlock *b;
if((b = vtcacheglobal(c, score, VtRootType, VtRootSize)) == nil)
goto Err;
if(vtrootunpack(&root, b->data) < 0)
goto Err;
if(root.blocksize < 512 || (root.blocksize&(root.blocksize-1))){
werrstr("bad blocksize %d", root.blocksize);
goto Err;
}
vtblockput(b);
if((b = vtcacheglobal(c, root.score, VtDirType, VtEntrySize)) == nil)
goto Err;
if(vtentryunpack(&e, b->data, 0) < 0)
goto Err;
vtblockput(b);
b = nil;
if((e.type&VtTypeBaseMask) != VtDataType){
werrstr("not a single file");
goto Err;
}
d = mallocz(sizeof(DiskVenti), 1);
if(d == nil)
goto Err;
d->disk._read = diskventiread;
d->disk._close = diskventiclose;
d->disk._size = diskventisize;
d->e = e;
d->c = c;
return &d->disk;
Err:
if(b)
vtblockput(b);
_nfilereads_darwin_sucks(); /* force Darwin ld to pull in file.o */
return nil;
}