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