This source file includes following definitions.
- lock_buffer
- unlock_buffer
- add_request
- make_request
- ll_rw_page
- ll_rw_block
- blk_dev_init
- ll_rw_swap_file
1
2
3
4
5
6
7
8
9
10 #include <errno.h>
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <asm/system.h>
14
15 #include "blk.h"
16
17
18
19
20
21 struct request request[NR_REQUEST];
22
23
24
25
26 struct task_struct * wait_for_request = NULL;
27
28
29
30
31
32 struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
33 { NULL, NULL },
34 { NULL, NULL },
35 { NULL, NULL },
36 { NULL, NULL },
37 { NULL, NULL },
38 { NULL, NULL },
39 { NULL, NULL },
40 { NULL, NULL },
41 { NULL, NULL },
42 { NULL, NULL }
43 };
44
45
46
47
48
49
50
51
52 int * blk_size[NR_BLK_DEV] = { NULL, NULL, };
53
54 static inline void lock_buffer(struct buffer_head * bh)
55 {
56 cli();
57 while (bh->b_lock)
58 sleep_on(&bh->b_wait);
59 bh->b_lock=1;
60 sti();
61 }
62
63 static inline void unlock_buffer(struct buffer_head * bh)
64 {
65 if (!bh->b_lock)
66 printk("ll_rw_block.c: buffer not locked\n\r");
67 bh->b_lock = 0;
68 wake_up(&bh->b_wait);
69 }
70
71
72
73
74
75
76
77
78
79 static void add_request(struct blk_dev_struct * dev, struct request * req)
80 {
81 struct request * tmp;
82
83 req->next = NULL;
84 cli();
85 if (req->bh)
86 req->bh->b_dirt = 0;
87 if (!(tmp = dev->current_request)) {
88 dev->current_request = req;
89 (dev->request_fn)();
90 sti();
91 return;
92 }
93 for ( ; tmp->next ; tmp = tmp->next) {
94 if (!req->bh)
95 if (tmp->next->bh)
96 break;
97 else
98 continue;
99 if ((IN_ORDER(tmp,req) ||
100 !IN_ORDER(tmp,tmp->next)) &&
101 IN_ORDER(req,tmp->next))
102 break;
103 }
104 req->next = tmp->next;
105 tmp->next = req;
106 sti();
107 }
108
109 static void make_request(int major,int rw, struct buffer_head * bh)
110 {
111 struct request * req;
112 int rw_ahead;
113
114
115
116 if (rw_ahead = (rw == READA || rw == WRITEA)) {
117 if (bh->b_lock)
118 return;
119 if (rw == READA)
120 rw = READ;
121 else
122 rw = WRITE;
123 }
124 if (rw!=READ && rw!=WRITE) {
125 printk("Bad block dev command, must be R/W/RA/WA\n");
126 return;
127 }
128 lock_buffer(bh);
129 if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
130 unlock_buffer(bh);
131 return;
132 }
133 repeat:
134 cli();
135 if (major == 3 && (req = blk_dev[major].current_request)) {
136 while (req = req->next) {
137 if (req->dev == bh->b_dev &&
138 !req->waiting &&
139 req->cmd == rw &&
140 req->sector + req->nr_sectors == bh->b_blocknr << 1 &&
141 req->nr_sectors < 254) {
142 req->bhtail->b_reqnext = bh;
143 req->bhtail = bh;
144 req->nr_sectors += 2;
145 bh->b_dirt = 0;
146 sti();
147 return;
148 }
149 }
150 }
151
152
153
154
155 if (rw == READ)
156 req = request+NR_REQUEST;
157 else
158 req = request+(NR_REQUEST/2);
159
160 while (--req >= request)
161 if (req->dev < 0)
162 goto found;
163
164 if (rw_ahead) {
165 sti();
166 unlock_buffer(bh);
167 return;
168 }
169 sleep_on(&wait_for_request);
170 sti();
171 goto repeat;
172
173 found: sti();
174
175 req->dev = bh->b_dev;
176 req->cmd = rw;
177 req->errors=0;
178 req->sector = bh->b_blocknr<<1;
179 req->nr_sectors = 2;
180 req->buffer = bh->b_data;
181 req->waiting = NULL;
182 req->bh = bh;
183 req->bhtail = bh;
184 req->next = NULL;
185 add_request(major+blk_dev,req);
186 }
187
188 void ll_rw_page(int rw, int dev, int page, char * buffer)
189 {
190 struct request * req;
191 unsigned int major = MAJOR(dev);
192
193 if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
194 printk("Trying to read nonexistent block-device\n\r");
195 return;
196 }
197 if (rw!=READ && rw!=WRITE)
198 panic("Bad block dev command, must be R/W");
199 cli();
200 repeat:
201 req = request+NR_REQUEST;
202 while (--req >= request)
203 if (req->dev<0)
204 break;
205 if (req < request) {
206 sleep_on(&wait_for_request);
207 goto repeat;
208 }
209 sti();
210
211 req->dev = dev;
212 req->cmd = rw;
213 req->errors = 0;
214 req->sector = page<<3;
215 req->nr_sectors = 8;
216 req->buffer = buffer;
217 req->waiting = current;
218 req->bh = NULL;
219 req->next = NULL;
220 current->state = TASK_UNINTERRUPTIBLE;
221 add_request(major+blk_dev,req);
222 schedule();
223 }
224
225 void ll_rw_block(int rw, struct buffer_head * bh)
226 {
227 unsigned int major;
228
229 if (!bh)
230 return;
231 if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
232 !(blk_dev[major].request_fn)) {
233 printk("ll_rw_block: Trying to read nonexistent block-device\n\r");
234 return;
235 }
236 make_request(major,rw,bh);
237 }
238
239 void blk_dev_init(void)
240 {
241 int i;
242
243 for (i=0 ; i<NR_REQUEST ; i++) {
244 request[i].dev = -1;
245 request[i].next = NULL;
246 }
247 }
248
249 void ll_rw_swap_file(int rw, int dev, unsigned int *b, int nb, char *buf)
250 {
251 int i;
252 struct request * req;
253 unsigned int major = MAJOR(dev);
254
255 if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
256 printk("ll_rw_swap_file: trying to swap nonexistent block-device\n\r");
257 return;
258 }
259
260 if (rw!=READ && rw!=WRITE) {
261 printk("ll_rw_swap: bad block dev command, must be R/W");
262 return;
263 }
264
265 for (i=0; i<nb; i++, buf += BLOCK_SIZE)
266 {
267 repeat:
268 req = request+NR_REQUEST;
269 while (--req >= request)
270 if (req->dev<0)
271 break;
272 if (req < request) {
273 sleep_on(&wait_for_request);
274 goto repeat;
275 }
276
277 req->dev = dev;
278 req->cmd = rw;
279 req->errors = 0;
280 req->sector = b[i] << 1;
281 req->nr_sectors = 2;
282 req->buffer = buf;
283 req->waiting = current;
284 req->bh = NULL;
285 req->next = NULL;
286 current->state = TASK_UNINTERRUPTIBLE;
287 add_request(major+blk_dev,req);
288 schedule();
289 }
290 }