This source file includes following definitions.
- ext_file_read
- ext_file_write
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <asm/segment.h>
16 #include <asm/system.h>
17
18 #include <linux/sched.h>
19 #include <linux/ext_fs.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/fcntl.h>
23 #include <linux/stat.h>
24 #include <linux/locks.h>
25 #include <linux/pagemap.h>
26
27 #define NBUF 32
28
29 #define MIN(a,b) (((a)<(b))?(a):(b))
30 #define MAX(a,b) (((a)>(b))?(a):(b))
31
32 #include <linux/fs.h>
33 #include <linux/ext_fs.h>
34
35 static int ext_file_read(struct inode *, struct file *, char *, int);
36 static int ext_file_write(struct inode *, struct file *, const char *, int);
37
38
39
40
41
42 static struct file_operations ext_file_operations = {
43 NULL,
44 ext_file_read,
45 ext_file_write,
46 NULL,
47 NULL,
48 NULL,
49 generic_file_mmap,
50 NULL,
51 NULL,
52 ext_sync_file
53 };
54
55 struct inode_operations ext_file_inode_operations = {
56 &ext_file_operations,
57 NULL,
58 NULL,
59 NULL,
60 NULL,
61 NULL,
62 NULL,
63 NULL,
64 NULL,
65 NULL,
66 NULL,
67 NULL,
68 generic_readpage,
69 NULL,
70 ext_bmap,
71 ext_truncate,
72 NULL
73 };
74
75 static int ext_file_read(struct inode * inode, struct file * filp, char * buf, int count)
76 {
77 int read,left,chars;
78 int block, blocks, offset;
79 int bhrequest, uptodate;
80 struct buffer_head ** bhb, ** bhe;
81 struct buffer_head * bhreq[NBUF];
82 struct buffer_head * buflist[NBUF];
83 unsigned int size;
84
85 if (!inode) {
86 printk("ext_file_read: inode = NULL\n");
87 return -EINVAL;
88 }
89 if (!S_ISREG(inode->i_mode)) {
90 printk("ext_file_read: mode = %07o\n",inode->i_mode);
91 return -EINVAL;
92 }
93 offset = filp->f_pos;
94 size = inode->i_size;
95 if (offset > size)
96 left = 0;
97 else
98 left = size - offset;
99 if (left > count)
100 left = count;
101 if (left <= 0)
102 return 0;
103 read = 0;
104 block = offset >> BLOCK_SIZE_BITS;
105 offset &= BLOCK_SIZE-1;
106 size = (size + (BLOCK_SIZE-1)) >> BLOCK_SIZE_BITS;
107 blocks = (left + offset + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
108 bhb = bhe = buflist;
109 if (filp->f_reada) {
110 if(blocks < read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9))
111 blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
112 if (block + blocks > size)
113 blocks = size - block;
114 }
115
116
117
118
119
120
121
122
123
124
125
126 do {
127 bhrequest = 0;
128 uptodate = 1;
129 while (blocks) {
130 --blocks;
131 *bhb = ext_getblk(inode, block++, 0);
132 if (*bhb && !buffer_uptodate(*bhb)) {
133 uptodate = 0;
134 bhreq[bhrequest++] = *bhb;
135 }
136
137 if (++bhb == &buflist[NBUF])
138 bhb = buflist;
139
140
141
142 if (uptodate)
143 break;
144 if (bhb == bhe)
145 break;
146 }
147
148
149 if (bhrequest)
150 ll_rw_block(READ, bhrequest, bhreq);
151
152 do {
153 if (*bhe) {
154 wait_on_buffer(*bhe);
155 if (!buffer_uptodate(*bhe)) {
156 brelse(*bhe);
157 if (++bhe == &buflist[NBUF])
158 bhe = buflist;
159 left = 0;
160 break;
161 }
162 }
163 if (left < BLOCK_SIZE - offset)
164 chars = left;
165 else
166 chars = BLOCK_SIZE - offset;
167 filp->f_pos += chars;
168 left -= chars;
169 read += chars;
170 if (*bhe) {
171 memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
172 brelse(*bhe);
173 buf += chars;
174 } else {
175 while (chars-->0)
176 put_user(0,buf++);
177 }
178 offset = 0;
179 if (++bhe == &buflist[NBUF])
180 bhe = buflist;
181 } while (left > 0 && bhe != bhb && (!*bhe || !buffer_locked(*bhe)));
182 } while (left > 0);
183
184
185 while (bhe != bhb) {
186 brelse(*bhe);
187 if (++bhe == &buflist[NBUF])
188 bhe = buflist;
189 };
190 if (!read)
191 return -EIO;
192 filp->f_reada = 1;
193 if (!IS_RDONLY(inode)) {
194 inode->i_atime = CURRENT_TIME;
195 inode->i_dirt = 1;
196 }
197 return read;
198 }
199
200 static int ext_file_write(struct inode * inode, struct file * filp, const char * buf, int count)
201 {
202 off_t pos;
203 int written,c;
204 struct buffer_head * bh;
205 char * p;
206
207 if (!inode) {
208 printk("ext_file_write: inode = NULL\n");
209 return -EINVAL;
210 }
211 if (!S_ISREG(inode->i_mode)) {
212 printk("ext_file_write: mode = %07o\n",inode->i_mode);
213 return -EINVAL;
214 }
215
216
217
218
219 if (filp->f_flags & O_APPEND)
220 pos = inode->i_size;
221 else
222 pos = filp->f_pos;
223 written = 0;
224 while (written<count) {
225 bh = ext_getblk(inode,pos/BLOCK_SIZE,1);
226 if (!bh) {
227 if (!written)
228 written = -ENOSPC;
229 break;
230 }
231 c = BLOCK_SIZE - (pos % BLOCK_SIZE);
232 if (c > count-written)
233 c = count-written;
234 if (c != BLOCK_SIZE && !buffer_uptodate(bh)) {
235 ll_rw_block(READ, 1, &bh);
236 wait_on_buffer(bh);
237 if (!buffer_uptodate(bh)) {
238 brelse(bh);
239 if (!written)
240 written = -EIO;
241 break;
242 }
243 }
244 p = (pos % BLOCK_SIZE) + bh->b_data;
245 memcpy_fromfs(p,buf,c);
246 update_vm_cache(inode, pos, p, c);
247 pos += c;
248 if (pos > inode->i_size) {
249 inode->i_size = pos;
250 inode->i_dirt = 1;
251 }
252 written += c;
253 buf += c;
254 mark_buffer_uptodate(bh, 1);
255 mark_buffer_dirty(bh, 0);
256 brelse(bh);
257 }
258 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
259 filp->f_pos = pos;
260 inode->i_dirt = 1;
261 return written;
262 }