Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <diskfs.h>
4 #include <venti.h>
6 extern void vtlibthread(void);
8 typedef struct DiskVenti DiskVenti;
9 struct DiskVenti
10 {
11 Disk disk;
12 VtEntry e;
13 VtCache *c;
14 };
16 extern int nfilereads;
17 extern void _nfilereads_darwin_sucks(void);
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;
30 memset(index, 0, VtPointerDepth*sizeof(int));
32 np = e->psize/VtScoreSize;
33 memset(index, 0, sizeof(index));
34 for(i=0; bn > 0; i++){
35 if(i >= VtPointerDepth){
36 werrstr("bad block number %lud", (ulong)bn);
37 return -1;
38 }
39 index[i] = bn % np;
40 bn /= np;
41 }
42 return i;
43 }
45 VtBlock *_vtfileblock(VtCache*, VtEntry*, u32int); /* avoid auto-inline by putting later in file */
46 static void
47 diskventiblockput(Block *b)
48 {
49 vtblockput(b->priv);
50 free(b);
51 }
53 static Block*
54 diskventiread(Disk *dd, u32int len, u64int offset)
55 {
56 DiskVenti *d = (DiskVenti*)dd;
57 VtBlock *vb;
58 Block *b;
59 int frag;
61 nfilereads++;
62 vb = _vtfileblock(d->c, &d->e, offset/d->e.dsize);
63 if(vb == nil)
64 return nil;
66 b = mallocz(sizeof(Block), 1);
67 if(b == nil){
68 vtblockput(vb);
69 return nil;
70 }
72 b->priv = vb;
73 b->_close = diskventiblockput;
74 frag = offset%d->e.dsize;
75 b->data = (uchar*)vb->data + frag;
76 b->len = d->e.dsize - frag;
77 if(b->len > len)
78 b->len = len;
79 return b;
80 }
82 VtBlock*
83 _vtfileblock(VtCache *c, VtEntry *e, u32int bn)
84 {
85 VtBlock *b;
86 int i, d, index[VtPointerDepth+1], t;
87 uchar score[VtScoreSize];
89 i = vtfileindices(e, bn, index);
90 if(i < 0)
91 return nil;
92 d = (e->type&VtTypeDepthMask);
93 if(i > d){
94 werrstr("bad address %d > %d (%x %x)", i, d, e->type, e->flags);
95 return nil;
96 }
98 /*fprint(2, "vtread %V\n", e->score); */
99 b = vtcacheglobal(c, e->score, e->type);
100 for(i=d-1; i>=0 && b; i--){
101 t = VtDataType+i;
102 /*fprint(2, "vtread %V\n", b->data+index[i]*VtScoreSize); */
103 memmove(score, b->data+index[i]*VtScoreSize, VtScoreSize);
104 vtblockput(b);
105 b = vtcacheglobal(c, score, t);
107 return b;
110 static void
111 diskventiclose(Disk *dd)
113 DiskVenti *d = (DiskVenti*)dd;
114 free(d);
117 Disk*
118 diskopenventi(VtCache *c, uchar score[VtScoreSize])
120 DiskVenti *d;
121 VtEntry e;
122 VtRoot root;
123 VtBlock *b;
125 if((b = vtcacheglobal(c, score, VtRootType)) == nil)
126 goto Err;
127 if(vtrootunpack(&root, b->data) < 0)
128 goto Err;
129 if(root.blocksize < 512 || (root.blocksize&(root.blocksize-1))){
130 werrstr("bad blocksize %d", root.blocksize);
131 goto Err;
133 vtblockput(b);
135 if((b = vtcacheglobal(c, root.score, VtDirType)) == nil)
136 goto Err;
137 if(vtentryunpack(&e, b->data, 0) < 0)
138 goto Err;
139 vtblockput(b);
140 b = nil;
141 if((e.type&VtTypeBaseMask) != VtDataType){
142 werrstr("not a single file");
143 goto Err;
146 d = mallocz(sizeof(DiskVenti), 1);
147 if(d == nil)
148 goto Err;
150 d->disk._read = diskventiread;
151 d->disk._close = diskventiclose;
152 d->e = e;
153 d->c = c;
154 return &d->disk;
156 Err:
157 if(b)
158 vtblockput(b);
160 _nfilereads_darwin_sucks(); /* force Darwin ld to pull in file.o */
161 return nil;