This source file includes following definitions.
- wait_on_buffer
- sys_sync
- sync_dev
- remove_from_queues
- insert_into_queues
- find_buffer
- get_hash_table
- getblk
- brelse
- bread
- buffer_init
1
2
3
4
5
6
7
8
9 #include <linux/config.h>
10 #include <linux/sched.h>
11 #include <linux/kernel.h>
12 #include <asm/system.h>
13
14 #if (BUFFER_END & 0xfff)
15 #error "Bad BUFFER_END value"
16 #endif
17
18 #if (BUFFER_END > 0xA0000 && BUFFER_END <= 0x100000)
19 #error "Bad BUFFER_END value"
20 #endif
21
22 extern int end;
23 struct buffer_head * start_buffer = (struct buffer_head *) &end;
24 struct buffer_head * hash_table[NR_HASH];
25 static struct buffer_head * free_list;
26 static struct task_struct * buffer_wait = NULL;
27 int NR_BUFFERS = 0;
28
29 static inline void wait_on_buffer(struct buffer_head * bh)
30 {
31 cli();
32 while (bh->b_lock)
33 sleep_on(&bh->b_wait);
34 sti();
35 }
36
37 int sys_sync(void)
38 {
39 int i;
40 struct buffer_head * bh;
41
42 sync_inodes();
43 bh = start_buffer;
44 for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
45 wait_on_buffer(bh);
46 if (bh->b_dirt)
47 ll_rw_block(WRITE,bh);
48 }
49 return 0;
50 }
51
52 static int sync_dev(int dev)
53 {
54 int i;
55 struct buffer_head * bh;
56
57 bh = start_buffer;
58 for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
59 if (bh->b_dev != dev)
60 continue;
61 wait_on_buffer(bh);
62 if (bh->b_dirt)
63 ll_rw_block(WRITE,bh);
64 }
65 return 0;
66 }
67
68 #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
69 #define hash(dev,block) hash_table[_hashfn(dev,block)]
70
71 static inline void remove_from_queues(struct buffer_head * bh)
72 {
73
74 if (bh->b_next)
75 bh->b_next->b_prev = bh->b_prev;
76 if (bh->b_prev)
77 bh->b_prev->b_next = bh->b_next;
78 if (hash(bh->b_dev,bh->b_blocknr) == bh)
79 hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
80
81 if (!(bh->b_prev_free) || !(bh->b_next_free))
82 panic("Free block list corrupted");
83 bh->b_prev_free->b_next_free = bh->b_next_free;
84 bh->b_next_free->b_prev_free = bh->b_prev_free;
85 if (free_list == bh)
86 free_list = bh->b_next_free;
87 }
88
89 static inline void insert_into_queues(struct buffer_head * bh)
90 {
91
92 bh->b_next_free = free_list;
93 bh->b_prev_free = free_list->b_prev_free;
94 free_list->b_prev_free->b_next_free = bh;
95 free_list->b_prev_free = bh;
96
97 bh->b_prev = NULL;
98 bh->b_next = NULL;
99 if (!bh->b_dev)
100 return;
101 bh->b_next = hash(bh->b_dev,bh->b_blocknr);
102 hash(bh->b_dev,bh->b_blocknr) = bh;
103 bh->b_next->b_prev = bh;
104 }
105
106 static struct buffer_head * find_buffer(int dev, int block)
107 {
108 struct buffer_head * tmp;
109
110 for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
111 if (tmp->b_dev==dev && tmp->b_blocknr==block)
112 return tmp;
113 return NULL;
114 }
115
116
117
118
119
120
121
122
123 struct buffer_head * get_hash_table(int dev, int block)
124 {
125 struct buffer_head * bh;
126
127 repeat:
128 if (!(bh=find_buffer(dev,block)))
129 return NULL;
130 bh->b_count++;
131 wait_on_buffer(bh);
132 if (bh->b_dev != dev || bh->b_blocknr != block) {
133 brelse(bh);
134 goto repeat;
135 }
136 return bh;
137 }
138
139
140
141
142
143
144 struct buffer_head * getblk(int dev,int block)
145 {
146 struct buffer_head * tmp;
147
148 repeat:
149 if (tmp=get_hash_table(dev,block))
150 return tmp;
151 tmp = free_list;
152 do {
153 if (!tmp->b_count) {
154 wait_on_buffer(tmp);
155 if (!tmp->b_count)
156 break;
157 }
158 tmp = tmp->b_next_free;
159 } while (tmp != free_list || (tmp=NULL));
160
161 if (!tmp) {
162 printk("Sleeping on free buffer ..");
163 sleep_on(&buffer_wait);
164 printk("ok\n");
165 goto repeat;
166 }
167 tmp->b_count++;
168 remove_from_queues(tmp);
169
170
171
172
173
174 if (tmp->b_dirt)
175 sync_dev(tmp->b_dev);
176
177 tmp->b_dev=dev;
178 tmp->b_blocknr=block;
179 tmp->b_dirt=0;
180 tmp->b_uptodate=0;
181
182
183
184 if (find_buffer(dev,block)) {
185 tmp->b_dev=0;
186 tmp->b_blocknr=0;
187 tmp->b_count=0;
188 insert_into_queues(tmp);
189 goto repeat;
190 }
191
192 insert_into_queues(tmp);
193 return tmp;
194 }
195
196 void brelse(struct buffer_head * buf)
197 {
198 if (!buf)
199 return;
200 wait_on_buffer(buf);
201 if (!(buf->b_count--))
202 panic("Trying to free free buffer");
203 wake_up(&buffer_wait);
204 }
205
206
207
208
209
210 struct buffer_head * bread(int dev,int block)
211 {
212 struct buffer_head * bh;
213
214 if (!(bh=getblk(dev,block)))
215 panic("bread: getblk returned NULL\n");
216 if (bh->b_uptodate)
217 return bh;
218 ll_rw_block(READ,bh);
219 if (bh->b_uptodate)
220 return bh;
221 brelse(bh);
222 return (NULL);
223 }
224
225 void buffer_init(void)
226 {
227 struct buffer_head * h = start_buffer;
228 void * b = (void *) BUFFER_END;
229 int i;
230
231 while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
232 h->b_dev = 0;
233 h->b_dirt = 0;
234 h->b_count = 0;
235 h->b_lock = 0;
236 h->b_uptodate = 0;
237 h->b_wait = NULL;
238 h->b_next = NULL;
239 h->b_prev = NULL;
240 h->b_data = (char *) b;
241 h->b_prev_free = h-1;
242 h->b_next_free = h+1;
243 h++;
244 NR_BUFFERS++;
245 if (b == (void *) 0x100000)
246 b = (void *) 0xA0000;
247 }
248 h--;
249 free_list = start_buffer;
250 free_list->b_prev_free = h;
251 h->b_next_free = free_list;
252 for (i=0;i<NR_HASH;i++)
253 hash_table[i]=NULL;
254 }