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