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