* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-0.99 / fs / block_dev.c
blob22ffc2154525fce136e95ff3c4ba00a367091f42
1 /*
2 * linux/fs/block_dev.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/locks.h>
11 #include <asm/segment.h>
12 #include <asm/system.h>
14 extern int *blk_size[];
15 extern int *blksize_size[];
17 int block_write(struct inode * inode, struct file * filp, char * buf, int count)
19 int blocksize, blocksize_bits, i;
20 int block;
21 int offset;
22 int chars;
23 int written = 0;
24 unsigned int size;
25 unsigned int dev;
26 struct buffer_head * bh;
27 register char * p;
29 dev = inode->i_rdev;
30 blocksize = BLOCK_SIZE;
31 if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
32 blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
34 i = blocksize;
35 blocksize_bits = 0;
36 while(i != 1) {
37 blocksize_bits++;
38 i >>= 1;
41 block = filp->f_pos >> blocksize_bits;
42 offset = filp->f_pos & (blocksize-1);
44 if (blk_size[MAJOR(dev)])
45 size = (blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS) >> blocksize_bits;
46 else
47 size = INT_MAX;
48 while (count>0) {
49 if (block >= size)
50 return written;
51 chars = blocksize - offset;
52 if (chars > count)
53 chars=count;
54 if (chars == blocksize)
55 bh = getblk(dev, block, blocksize);
56 else
57 bh = breada(dev,block,block+1,block+2,-1);
58 block++;
59 if (!bh)
60 return written?written:-EIO;
61 p = offset + bh->b_data;
62 offset = 0;
63 filp->f_pos += chars;
64 written += chars;
65 count -= chars;
66 memcpy_fromfs(p,buf,chars);
67 p += chars;
68 buf += chars;
69 bh->b_uptodate = 1;
70 bh->b_dirt = 1;
71 brelse(bh);
73 return written;
76 #define NBUF 32
78 int block_read(struct inode * inode, struct file * filp, char * buf, int count)
80 unsigned int block;
81 unsigned int offset;
82 int blocksize;
83 int blocksize_bits, i;
84 unsigned int left;
85 unsigned int blocks;
86 int bhrequest, uptodate;
87 struct buffer_head ** bhb, ** bhe;
88 struct buffer_head * buflist[NBUF];
89 struct buffer_head * bhreq[NBUF];
90 unsigned int chars;
91 unsigned int size;
92 unsigned int dev;
93 int read;
95 dev = inode->i_rdev;
96 blocksize = BLOCK_SIZE;
97 if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
98 blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
99 i = blocksize;
100 blocksize_bits = 0;
101 while (i != 1) {
102 blocksize_bits++;
103 i >>= 1;
106 offset = filp->f_pos;
107 if (blk_size[MAJOR(dev)])
108 size = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
109 else
110 size = INT_MAX;
112 if (offset > size)
113 left = 0;
114 else
115 left = size - offset;
116 if (left > count)
117 left = count;
118 if (left <= 0)
119 return 0;
120 read = 0;
121 block = offset >> blocksize_bits;
122 offset &= blocksize-1;
123 size >>= blocksize_bits;
124 blocks = (left + offset + blocksize - 1) >> blocksize_bits;
125 bhb = bhe = buflist;
126 if (filp->f_reada) {
127 blocks += read_ahead[MAJOR(dev)] / (blocksize >> 9);
128 if (block + blocks > size)
129 blocks = size - block;
132 /* We do this in a two stage process. We first try and request
133 as many blocks as we can, then we wait for the first one to
134 complete, and then we try and wrap up as many as are actually
135 done. This routine is rather generic, in that it can be used
136 in a filesystem by substituting the appropriate function in
137 for getblk.
139 This routine is optimized to make maximum use of the various
140 buffers and caches. */
142 do {
143 bhrequest = 0;
144 uptodate = 1;
145 while (blocks) {
146 --blocks;
147 *bhb = getblk(dev, block++, blocksize);
148 if (*bhb && !(*bhb)->b_uptodate) {
149 uptodate = 0;
150 bhreq[bhrequest++] = *bhb;
153 if (++bhb == &buflist[NBUF])
154 bhb = buflist;
156 /* If the block we have on hand is uptodate, go ahead
157 and complete processing. */
158 if (uptodate)
159 break;
160 if (bhb == bhe)
161 break;
164 /* Now request them all */
165 if (bhrequest)
166 ll_rw_block(READ, bhrequest, bhreq);
168 do { /* Finish off all I/O that has actually completed */
169 if (*bhe) {
170 wait_on_buffer(*bhe);
171 if (!(*bhe)->b_uptodate) { /* read error? */
172 brelse(*bhe);
173 if (++bhe == &buflist[NBUF])
174 bhe = buflist;
175 left = 0;
176 break;
179 if (left < blocksize - offset)
180 chars = left;
181 else
182 chars = blocksize - offset;
183 filp->f_pos += chars;
184 left -= chars;
185 read += chars;
186 if (*bhe) {
187 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
188 brelse(*bhe);
189 buf += chars;
190 } else {
191 while (chars-->0)
192 put_fs_byte(0,buf++);
194 offset = 0;
195 if (++bhe == &buflist[NBUF])
196 bhe = buflist;
197 } while (left > 0 && bhe != bhb && (!*bhe || !(*bhe)->b_lock));
198 } while (left > 0);
200 /* Release the read-ahead blocks */
201 while (bhe != bhb) {
202 brelse(*bhe);
203 if (++bhe == &buflist[NBUF])
204 bhe = buflist;
206 if (!read)
207 return -EIO;
208 filp->f_reada = 1;
209 return read;
212 int block_fsync(struct inode *inode, struct file *filp)
214 return fsync_dev (inode->i_rdev);