tventi.c - 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
       ---
       tventi.c (3242B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <diskfs.h>
            4 #include <venti.h>
            5 
            6 extern void vtlibthread(void);
            7 
            8 typedef struct DiskVenti DiskVenti;
            9 struct DiskVenti
           10 {
           11         Disk disk;
           12         VtEntry e;
           13         VtCache *c;
           14 };
           15 
           16 extern int nfilereads;
           17 extern void _nfilereads_darwin_sucks(void);
           18 
           19 /*
           20  * This part is like file.c but doesn't require storing the root block
           21  * in the cache permanently and doesn't care about locking since
           22  * all the blocks are read-only.  Perhaps at some point this functionality
           23  * should go into libvac in some form.
           24  */
           25 static int
           26 vtfileindices(VtEntry *e, u32int bn, int *index)
           27 {
           28         int i, np;
           29 
           30         memset(index, 0, VtPointerDepth*sizeof(int));
           31 
           32         np = e->psize/VtScoreSize;
           33         for(i=0; bn > 0; i++){
           34                 if(i >= VtPointerDepth){
           35                         werrstr("bad block number %lud", (ulong)bn);
           36                         return -1;
           37                 }
           38                 index[i] = bn % np;
           39                 bn /= np;
           40         }
           41         return i;
           42 }
           43 
           44 VtBlock *_vtfileblock(VtCache*, VtEntry*, u32int);        /* avoid auto-inline by putting later in file */
           45 static void
           46 diskventiblockput(Block *b)
           47 {
           48         vtblockput(b->priv);
           49         free(b);
           50 }
           51 
           52 static Block*
           53 diskventiread(Disk *dd, u32int len, u64int offset)
           54 {
           55         DiskVenti *d = (DiskVenti*)dd;
           56         VtBlock *vb;
           57         Block *b;
           58         int frag;
           59 
           60 nfilereads++;
           61         vb = _vtfileblock(d->c, &d->e, offset/d->e.dsize);
           62         if(vb == nil)
           63                 return nil;
           64 
           65         b = mallocz(sizeof(Block), 1);
           66         if(b == nil){
           67                 vtblockput(vb);
           68                 return nil;
           69         }
           70 
           71         b->priv = vb;
           72         b->_close = diskventiblockput;
           73         frag = offset%d->e.dsize;
           74         b->data = (uchar*)vb->data + frag;
           75         b->len = d->e.dsize - frag;
           76         if(b->len > len)
           77                 b->len = len;
           78         return b;
           79 }
           80 
           81 VtBlock*
           82 _vtfileblock(VtCache *c, VtEntry *e, u32int bn)
           83 {
           84         VtBlock *b;
           85         int i, d, index[VtPointerDepth+1], t;
           86         uchar score[VtScoreSize];
           87 
           88         i = vtfileindices(e, bn, index);
           89         if(i < 0)
           90                 return nil;
           91         d = (e->type&VtTypeDepthMask);
           92         if(i > d){
           93                 werrstr("bad address %d > %d (%x %x)", i, d, e->type, e->flags);
           94                 return nil;
           95         }
           96 
           97 /*fprint(2, "vtread %V\n", e->score); */
           98         b = vtcacheglobal(c, e->score, e->type, d == 0 ? e->dsize : e->psize);
           99         for(i=d-1; i>=0 && b; i--){
          100                 t = VtDataType+i;
          101 /*fprint(2, "vtread %V\n", b->data+index[i]*VtScoreSize); */
          102                 memmove(score, b->data+index[i]*VtScoreSize, VtScoreSize);
          103                 vtblockput(b);
          104                 b = vtcacheglobal(c, score, t, i == 0 ? e->dsize : e->psize);
          105         }
          106         return b;
          107 }
          108 
          109 static void
          110 diskventiclose(Disk *dd)
          111 {
          112         DiskVenti *d = (DiskVenti*)dd;
          113         free(d);
          114 }
          115 
          116 Disk*
          117 diskopenventi(VtCache *c, uchar score[VtScoreSize])
          118 {
          119         DiskVenti *d;
          120         VtEntry e;
          121         VtRoot root;
          122         VtBlock *b;
          123 
          124         if((b = vtcacheglobal(c, score, VtRootType, VtRootSize)) == nil)
          125                 goto Err;
          126         if(vtrootunpack(&root, b->data) < 0)
          127                 goto Err;
          128         if(root.blocksize < 512 || (root.blocksize&(root.blocksize-1))){
          129                 werrstr("bad blocksize %d", root.blocksize);
          130                 goto Err;
          131         }
          132         vtblockput(b);
          133 
          134         if((b = vtcacheglobal(c, root.score, VtDirType, VtEntrySize)) == nil)
          135                 goto Err;
          136         if(vtentryunpack(&e, b->data, 0) < 0)
          137                 goto Err;
          138         vtblockput(b);
          139         b = nil;
          140         if((e.type&VtTypeBaseMask) != VtDataType){
          141                 werrstr("not a single file");
          142                 goto Err;
          143         }
          144 
          145         d = mallocz(sizeof(DiskVenti), 1);
          146         if(d == nil)
          147                 goto Err;
          148 
          149         d->disk._read = diskventiread;
          150         d->disk._close = diskventiclose;
          151         d->e = e;
          152         d->c = c;
          153         return &d->disk;
          154 
          155 Err:
          156         if(b)
          157                 vtblockput(b);
          158 
          159         _nfilereads_darwin_sucks();  /* force Darwin ld to pull in file.o */
          160         return nil;
          161 }