This source file includes following definitions.
- block_write
- block_read
- block_fsync
1
2
3
4
5
6
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/locks.h>
11 #include <linux/fcntl.h>
12 #include <linux/mm.h>
13
14 #include <asm/segment.h>
15 #include <asm/system.h>
16
17 extern int *blk_size[];
18 extern int *blksize_size[];
19
20 #define MAX_BUF_PER_PAGE (PAGE_SIZE / 512)
21 #define NBUF 64
22
23 int block_write(struct inode * inode, struct file * filp, const char * buf, int count)
24 {
25 int blocksize, blocksize_bits, i, j, buffercount,write_error;
26 int block, blocks;
27 loff_t offset;
28 int chars;
29 int written = 0;
30 int cluster_list[MAX_BUF_PER_PAGE];
31 struct buffer_head * bhlist[NBUF];
32 int blocks_per_cluster;
33 unsigned int size;
34 kdev_t dev;
35 struct buffer_head * bh, *bufferlist[NBUF];
36 register char * p;
37 int excess;
38
39 write_error = buffercount = 0;
40 dev = inode->i_rdev;
41 if ( is_read_only( inode->i_rdev ))
42 return -EPERM;
43 blocksize = BLOCK_SIZE;
44 if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
45 blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
46
47 i = blocksize;
48 blocksize_bits = 0;
49 while(i != 1) {
50 blocksize_bits++;
51 i >>= 1;
52 }
53
54 blocks_per_cluster = PAGE_SIZE / blocksize;
55
56 block = filp->f_pos >> blocksize_bits;
57 offset = filp->f_pos & (blocksize-1);
58
59 if (blk_size[MAJOR(dev)])
60 size = ((loff_t) blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS) >> blocksize_bits;
61 else
62 size = INT_MAX;
63 while (count>0) {
64 if (block >= size) {
65 if (!written)
66 written = -ENOSPC;
67 return written;
68 }
69 chars = blocksize - offset;
70 if (chars > count)
71 chars=count;
72
73 #if 0
74 if (chars == blocksize)
75 bh = getblk(dev, block, blocksize);
76 else
77 bh = breada(dev,block,block+1,block+2,-1);
78
79 #else
80 for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
81 if((block % blocks_per_cluster) == 0)
82 generate_cluster(dev, cluster_list, blocksize);
83 bh = getblk(dev, block, blocksize);
84
85 if (chars != blocksize && !buffer_uptodate(bh)) {
86 if(!filp->f_reada ||
87 !read_ahead[MAJOR(dev)]) {
88
89 brelse(bh);
90 bh = bread(dev,block,blocksize);
91 } else {
92
93 blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9) / 2;
94 if (block + blocks > size) blocks = size - block;
95 if (blocks > NBUF) blocks=NBUF;
96 excess = (block + blocks) % blocks_per_cluster;
97 if ( blocks > excess )
98 blocks -= excess;
99 bhlist[0] = bh;
100 for(i=1; i<blocks; i++){
101 if(((i+block) % blocks_per_cluster) == 0) {
102 for(j=0; j<blocks_per_cluster; j++) cluster_list[j] = block+i+j;
103 generate_cluster(dev, cluster_list, blocksize);
104 };
105 bhlist[i] = getblk (dev, block+i, blocksize);
106 if(!bhlist[i]){
107 while(i >= 0) brelse(bhlist[i--]);
108 return written? written: -EIO;
109 };
110 };
111 ll_rw_block(READ, blocks, bhlist);
112 for(i=1; i<blocks; i++) brelse(bhlist[i]);
113 wait_on_buffer(bh);
114
115 };
116 };
117 #endif
118 block++;
119 if (!bh)
120 return written?written:-EIO;
121 p = offset + bh->b_data;
122 offset = 0;
123 filp->f_pos += chars;
124 written += chars;
125 count -= chars;
126 memcpy_fromfs(p,buf,chars);
127 p += chars;
128 buf += chars;
129 mark_buffer_uptodate(bh, 1);
130 mark_buffer_dirty(bh, 0);
131 if (filp->f_flags & O_SYNC)
132 bufferlist[buffercount++] = bh;
133 else
134 brelse(bh);
135 if (buffercount == NBUF){
136 ll_rw_block(WRITE, buffercount, bufferlist);
137 for(i=0; i<buffercount; i++){
138 wait_on_buffer(bufferlist[i]);
139 if (!buffer_uptodate(bufferlist[i]))
140 write_error=1;
141 brelse(bufferlist[i]);
142 }
143 buffercount=0;
144 }
145 if(write_error)
146 break;
147 }
148 if ( buffercount ){
149 ll_rw_block(WRITE, buffercount, bufferlist);
150 for(i=0; i<buffercount; i++){
151 wait_on_buffer(bufferlist[i]);
152 if (!buffer_uptodate(bufferlist[i]))
153 write_error=1;
154 brelse(bufferlist[i]);
155 }
156 }
157 filp->f_reada = 1;
158 if(write_error)
159 return -EIO;
160 return written;
161 }
162
163 int block_read(struct inode * inode, struct file * filp, char * buf, int count)
164 {
165 unsigned int block;
166 loff_t offset;
167 int blocksize;
168 int blocksize_bits, i;
169 unsigned int blocks, rblocks, left;
170 int bhrequest, uptodate;
171 int cluster_list[MAX_BUF_PER_PAGE];
172 int blocks_per_cluster;
173 struct buffer_head ** bhb, ** bhe;
174 struct buffer_head * buflist[NBUF];
175 struct buffer_head * bhreq[NBUF];
176 unsigned int chars;
177 loff_t size;
178 kdev_t dev;
179 int read;
180 int excess;
181
182 dev = inode->i_rdev;
183 blocksize = BLOCK_SIZE;
184 if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
185 blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
186 i = blocksize;
187 blocksize_bits = 0;
188 while (i != 1) {
189 blocksize_bits++;
190 i >>= 1;
191 }
192
193 offset = filp->f_pos;
194 if (blk_size[MAJOR(dev)])
195 size = (loff_t) blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
196 else
197 size = INT_MAX;
198
199 blocks_per_cluster = PAGE_SIZE / blocksize;
200
201 if (offset > size)
202 left = 0;
203
204 else if (size - offset > INT_MAX)
205 left = INT_MAX;
206 else
207 left = size - offset;
208 if (left > count)
209 left = count;
210 if (left <= 0)
211 return 0;
212 read = 0;
213 block = offset >> blocksize_bits;
214 offset &= blocksize-1;
215 size >>= blocksize_bits;
216 rblocks = blocks = (left + offset + blocksize - 1) >> blocksize_bits;
217 bhb = bhe = buflist;
218 if (filp->f_reada) {
219 if (blocks < read_ahead[MAJOR(dev)] / (blocksize >> 9))
220 blocks = read_ahead[MAJOR(dev)] / (blocksize >> 9);
221 excess = (block + blocks) % blocks_per_cluster;
222 if ( blocks > excess )
223 blocks -= excess;
224 if (rblocks > blocks)
225 blocks = rblocks;
226
227 }
228 if (block + blocks > size)
229 blocks = size - block;
230
231
232
233
234
235
236
237
238
239
240
241 do {
242 bhrequest = 0;
243 uptodate = 1;
244 while (blocks) {
245 --blocks;
246 #if 1
247 if((block % blocks_per_cluster) == 0) {
248 for(i=0; i<blocks_per_cluster; i++) cluster_list[i] = block+i;
249 generate_cluster(dev, cluster_list, blocksize);
250 }
251 #endif
252 *bhb = getblk(dev, block++, blocksize);
253 if (*bhb && !buffer_uptodate(*bhb)) {
254 uptodate = 0;
255 bhreq[bhrequest++] = *bhb;
256 }
257
258 if (++bhb == &buflist[NBUF])
259 bhb = buflist;
260
261
262
263 if (uptodate)
264 break;
265 if (bhb == bhe)
266 break;
267 }
268
269
270 if (bhrequest) {
271 ll_rw_block(READ, bhrequest, bhreq);
272 refill_freelist(blocksize);
273 }
274
275 do {
276 if (*bhe) {
277 wait_on_buffer(*bhe);
278 if (!buffer_uptodate(*bhe)) {
279 brelse(*bhe);
280 if (++bhe == &buflist[NBUF])
281 bhe = buflist;
282 left = 0;
283 break;
284 }
285 }
286 if (left < blocksize - offset)
287 chars = left;
288 else
289 chars = blocksize - offset;
290 filp->f_pos += chars;
291 left -= chars;
292 read += chars;
293 if (*bhe) {
294 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
295 brelse(*bhe);
296 buf += chars;
297 } else {
298 while (chars-- > 0)
299 put_user(0,buf++);
300 }
301 offset = 0;
302 if (++bhe == &buflist[NBUF])
303 bhe = buflist;
304 } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
305 } while (left > 0);
306
307
308 while (bhe != bhb) {
309 brelse(*bhe);
310 if (++bhe == &buflist[NBUF])
311 bhe = buflist;
312 };
313 if (!read)
314 return -EIO;
315 filp->f_reada = 1;
316 return read;
317 }
318
319 int block_fsync(struct inode *inode, struct file *filp)
320 {
321 return fsync_dev (inode->i_rdev);
322 }