]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ext2srv/iobuf.c
merge
[plan9front.git] / sys / src / cmd / ext2srv / iobuf.c
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*
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
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
85 dirtybuf(Iobuf *p)
86 {
87         if(p->busy <=0)
88                 panic("dirtybuf");
89         p->dirty = 1;
90 }
91 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
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
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
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 
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
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 }