1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <thread.h>
5 #include <9p.h>
6 #include "dat.h"
7 #include "fns.h"
8
9 #define NIOBUF 100
10 #define HIOB (NIOBUF/3)
11
12 static Iobuf* hiob[HIOB]; /* hash buckets */
13 static Iobuf iobuf[NIOBUF]; /* buffer headers */
14 static Iobuf* iohead;
15 static Iobuf* iotail;
16
17 Iobuf*
getbuf(Xfs * dev,long addr)18 getbuf(Xfs *dev, long addr)
19 {
20 Iobuf *p, *h, **l, **f;
21
22 l = &hiob[addr%HIOB];
23 for(p = *l; p; p = p->hash) {
24 if(p->addr == addr && p->dev == dev) {
25 p->busy++;
26 return p;
27 }
28 }
29 /* Find a non-busy buffer from the tail */
30 for(p = iotail; p && (p->busy > 0); p = p->prev)
31 ;
32 if(!p)
33 panic("all buffers busy");
34 if(p->dirty){
35 xwrite(p);
36 p->dirty = 0;
37 }
38
39 if( xread(dev, p, addr) < 0)
40 return 0;
41 /* Delete from hash chain */
42 f = &hiob[p->addr%HIOB];
43 if( *f == p )
44 *f = p->hash;
45 else {
46 for(h = *f; h ; h = h->hash)
47 if( h->hash == p ){
48 h->hash = p->hash;
49 break;
50 }
51 }
52 /* Fill and hash */
53 p->hash = *l;
54 *l = p;
55 p->addr = addr;
56 p->dev = dev;
57 p->busy=1;
58
59 return p;
60 }
61 void
putbuf(Iobuf * p)62 putbuf(Iobuf *p)
63 {
64 if(p->busy <= 0)
65 panic("putbuf");
66 p->busy--;
67
68 /* Link onto head for lru */
69 if(p == iohead)
70 return;
71 if( p == iotail ){
72 p->prev->next = 0;
73 iotail = p->prev;
74 }else{
75 p->prev->next = p->next;
76 p->next->prev = p->prev;
77 }
78
79 p->prev = 0;
80 p->next = iohead;
81 iohead->prev = p;
82 iohead = p;
83 }
84 void
dirtybuf(Iobuf * p)85 dirtybuf(Iobuf *p)
86 {
87 if(p->busy <=0)
88 panic("dirtybuf");
89 p->dirty = 1;
90 }
91 void
syncbuf(void)92 syncbuf(void)
93 {
94 Iobuf *p;
95
96 for(p=&iobuf[0] ; p<&iobuf[NIOBUF]; p++)
97 if( p->dirty ){
98 xwrite(p);
99 p->dirty = 0;
100 }
101 }
102 void
purgebuf(Xfs * dev)103 purgebuf(Xfs *dev)
104 {
105 Iobuf *p;
106
107 for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++)
108 if(p->dev == dev)
109 p->busy = 0;
110
111 /* Blow hash chains */
112 memset(hiob, 0, sizeof(hiob));
113 }
114 void
iobuf_init(void)115 iobuf_init(void)
116 {
117 Iobuf *p;
118
119 iohead = iobuf;
120 iotail = iobuf+NIOBUF-1;
121
122 for(p = iobuf; p <= iotail; p++) {
123 p->next = p+1;
124 p->prev = p-1;
125
126 p->iobuf = (char *)malloc(EXT2_MAX_BLOCK_SIZE);
127 if(p->iobuf == 0)
128 panic("iobuf_init");
129 }
130
131 iohead->prev = 0;
132 iotail->next = 0;
133 }
134 int
xread(Xfs * dev,Iobuf * p,long addr)135 xread(Xfs *dev, Iobuf *p, long addr)
136 {
137 /*chat("xread %d,%d...", dev->dev, addr);*/
138
139 seek(dev->dev, (vlong)addr*dev->block_size, 0);
140 if(read(dev->dev, p->iobuf, dev->block_size) != dev->block_size){
141 chat("xread %d, block=%d failed ...", dev->dev, addr);
142 errno = Eio;
143 return -1;
144 }
145 /*chat("xread ok...");*/
146 return 0;
147 }
148 void
xwrite(Iobuf * p)149 xwrite(Iobuf *p)
150 {
151 Xfs *dev;
152 long addr;
153
154 dev = p->dev;
155 addr = p->addr;
156 /*chat("xwrite %d,%d...", dev->dev, addr);*/
157
158 seek(dev->dev, (vlong)addr*dev->block_size, 0);
159 if(write(dev->dev, p->iobuf, dev->block_size) != dev->block_size){
160 chat("xwrite %d, block=%d failed ...", dev->dev, addr);
161 errno = Eio;
162 return;
163 }
164 /*chat("xwrite ok...");*/
165 }
166 void
dumpbuf(void)167 dumpbuf(void)
168 {
169 Iobuf *p;
170
171 for(p = iotail; p ; p = p->prev)
172 if( p->busy )
173 mchat("\nHi ERROR buf(%x, %d, %d)\n", p, p->addr, p->busy);
174 }
175