This source file includes following definitions.
- fat_prefetch
- fat_file_read
- fat_file_write
- fat_truncate
1
2
3
4
5
6
7
8
9 #include <linux/sched.h>
10 #include <linux/locks.h>
11 #include <linux/fs.h>
12 #include <linux/msdos_fs.h>
13 #include <linux/errno.h>
14 #include <linux/fcntl.h>
15 #include <linux/stat.h>
16 #include <linux/string.h>
17 #include <linux/pagemap.h>
18
19 #include <asm/segment.h>
20 #include <asm/system.h>
21
22 #include "msbuffer.h"
23
24 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
25 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
26
27 #define PRINTK(x)
28 #define Printk(x) printk x
29
30 static struct file_operations fat_file_operations = {
31 NULL,
32 fat_file_read,
33 fat_file_write,
34 NULL,
35 NULL,
36 NULL,
37 generic_file_mmap,
38 NULL,
39 NULL,
40 file_fsync
41 };
42
43 struct inode_operations fat_file_inode_operations = {
44 &fat_file_operations,
45 NULL,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 NULL,
56 generic_readpage,
57 NULL,
58 fat_bmap,
59 fat_truncate,
60 NULL,
61 NULL
62 };
63
64
65
66
67
68
69 static struct file_operations fat_file_operations_1024 = {
70 NULL,
71 fat_file_read,
72 fat_file_write,
73 NULL,
74 NULL,
75 NULL,
76 fat_mmap,
77 NULL,
78 NULL,
79 file_fsync
80 };
81
82
83
84
85
86
87
88
89
90
91 struct inode_operations fat_file_inode_operations_1024 = {
92 &fat_file_operations_1024,
93 NULL,
94 NULL,
95 NULL,
96 NULL,
97 NULL,
98 NULL,
99 NULL,
100 NULL,
101 NULL,
102 NULL,
103 NULL,
104 NULL,
105 NULL,
106 NULL,
107 fat_truncate,
108 NULL,
109 NULL
110 };
111
112 #define MSDOS_PREFETCH 32
113 struct fat_pre {
114 int file_sector;
115
116 struct buffer_head *bhlist[MSDOS_PREFETCH];
117 int nblist;
118 int nolist;
119 };
120
121
122
123 static void fat_prefetch (
124 struct inode *inode,
125 struct fat_pre *pre,
126 int nb)
127 {
128 struct super_block *sb = inode->i_sb;
129 struct buffer_head *bhreq[MSDOS_PREFETCH];
130
131 int nbreq=0;
132 int i;
133 for (i=0; i<nb; i++){
134 int sector = fat_smap(inode,pre->file_sector);
135 if (sector != 0){
136 struct buffer_head *bh;
137 PRINTK (("fsector2 %d -> %d\n",pre->file_sector-1,sector));
138 pre->file_sector++;
139 bh = getblk(inode->i_dev,sector,SECTOR_SIZE);
140 if (bh == NULL) break;
141 pre->bhlist[pre->nblist++] = bh;
142 if (!fat_is_uptodate(sb,bh)) bhreq[nbreq++] = bh;
143 }else{
144 break;
145 }
146 }
147 if (nbreq > 0) fat_ll_rw_block (sb,READ,nbreq,bhreq);
148 for (i=pre->nblist; i<MSDOS_PREFETCH; i++) pre->bhlist[i] = NULL;
149 }
150
151
152
153
154 int fat_file_read(
155 struct inode *inode,
156 struct file *filp,
157 char *buf,
158 int count)
159 {
160 struct super_block *sb = inode->i_sb;
161 char *start = buf;
162 char *end = buf + count;
163 int i;
164 int left_in_file;
165 struct fat_pre pre;
166
167
168 if (!inode) {
169 printk("fat_file_read: inode = NULL\n");
170 return -EINVAL;
171 }
172
173 if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
174 printk("fat_file_read: mode = %07o\n",inode->i_mode);
175 return -EINVAL;
176 }
177 if (filp->f_pos >= inode->i_size || count <= 0) return 0;
178
179
180
181
182
183
184
185
186
187 PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode->i_ino,filp->f_pos,inode->i_size,count));
188 {
189
190
191
192
193 int count_max = (filp->f_pos & (SECTOR_SIZE-1)) + count;
194 int to_reada;
195 pre.file_sector = filp->f_pos >> SECTOR_BITS;
196 to_reada = count_max / SECTOR_SIZE;
197 if (count_max & (SECTOR_SIZE-1)) to_reada++;
198 if (filp->f_reada || !MSDOS_I(inode)->i_binary){
199
200
201
202 int ahead = read_ahead[MAJOR(inode->i_dev)];
203 PRINTK (("to_reada %d ahead %d\n",to_reada,ahead));
204 if (ahead == 0) ahead = 8;
205 to_reada += ahead;
206 }
207 if (to_reada > MSDOS_PREFETCH) to_reada = MSDOS_PREFETCH;
208 pre.nblist = 0;
209 fat_prefetch (inode,&pre,to_reada);
210 }
211 pre.nolist = 0;
212 PRINTK (("count %d ahead %d nblist %d\n",count,read_ahead[MAJOR(inode->i_dev)],pre.nblist));
213 while ((left_in_file = inode->i_size - filp->f_pos) > 0
214 && buf < end){
215 struct buffer_head *bh = pre.bhlist[pre.nolist];
216 char *data;
217 int size,offset;
218 if (bh == NULL) break;
219 pre.bhlist[pre.nolist] = NULL;
220 pre.nolist++;
221 if (pre.nolist == MSDOS_PREFETCH/2){
222 memcpy (pre.bhlist,pre.bhlist+MSDOS_PREFETCH/2
223 ,(MSDOS_PREFETCH/2)*sizeof(pre.bhlist[0]));
224 pre.nblist -= MSDOS_PREFETCH/2;
225 fat_prefetch (inode,&pre,MSDOS_PREFETCH/2);
226 pre.nolist = 0;
227 }
228 PRINTK (("file_read pos %ld nblist %d %d %d\n",filp->f_pos,pre.nblist,pre.fetched,count));
229 wait_on_buffer(bh);
230 if (!fat_is_uptodate(sb,bh)){
231
232 brelse (bh);
233 break;
234 }
235 offset = filp->f_pos & (SECTOR_SIZE-1);
236 data = bh->b_data + offset;
237 size = MIN(SECTOR_SIZE-offset,left_in_file);
238 if (MSDOS_I(inode)->i_binary) {
239 size = MIN(size,end-buf);
240 memcpy_tofs(buf,data,size);
241 buf += size;
242 filp->f_pos += size;
243 }else{
244 for (; size && buf < end; size--) {
245 char ch = *data++;
246 filp->f_pos++;
247 if (ch == 26){
248 filp->f_pos = inode->i_size;
249 break;
250 }else if (ch != '\r'){
251 put_user(ch,buf++);
252 }
253 }
254 }
255 brelse(bh);
256 }
257 PRINTK (("--- %d -> %d\n",count,(int)(buf-start)));
258 for (i=0; i<pre.nblist; i++) brelse (pre.bhlist[i]);
259 if (start == buf) return -EIO;
260 if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
261 filp->f_reada = 1;
262 return buf-start;
263 }
264
265
266
267
268 int fat_file_write(
269 struct inode *inode,
270 struct file *filp,
271 const char *buf,
272 int count)
273 {
274 struct super_block *sb = inode->i_sb;
275 int sector,offset,size,left,written;
276 int error,carry;
277 const char *start;
278 char *to,ch;
279 struct buffer_head *bh;
280 int binary_mode = MSDOS_I(inode)->i_binary;
281
282 if (!inode) {
283 printk("fat_file_write: inode = NULL\n");
284 return -EINVAL;
285 }
286
287 if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
288 printk("fat_file_write: mode = %07o\n",inode->i_mode);
289 return -EINVAL;
290 }
291
292 if (IS_IMMUTABLE(inode)) return -EPERM;
293
294
295
296
297 if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
298 if (count <= 0) return 0;
299 error = carry = 0;
300 for (start = buf; count || carry; count -= size) {
301 while (!(sector = fat_smap(inode,filp->f_pos >> SECTOR_BITS)))
302 if ((error = fat_add_cluster(inode)) < 0) break;
303 if (error) {
304 fat_truncate(inode);
305 break;
306 }
307 offset = filp->f_pos & (SECTOR_SIZE-1);
308 size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
309 if (binary_mode
310 && offset == 0
311 && (size == SECTOR_SIZE
312 || filp->f_pos + size >= inode->i_size)){
313
314
315
316 if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE))){
317 error = -EIO;
318 break;
319 }
320 }else if (!(bh = bread(inode->i_dev,sector,SECTOR_SIZE))) {
321 error = -EIO;
322 break;
323 }
324 if (binary_mode) {
325 memcpy_fromfs(bh->b_data+offset,buf,written = size);
326 buf += size;
327 }
328 else {
329 written = left = SECTOR_SIZE-offset;
330 to = (char *) bh->b_data+(filp->f_pos & (SECTOR_SIZE-1));
331 if (carry) {
332 *to++ = '\n';
333 left--;
334 carry = 0;
335 }
336 for (size = 0; size < count && left; size++) {
337 if ((ch = get_user(buf++)) == '\n') {
338 *to++ = '\r';
339 left--;
340 }
341 if (!left) carry = 1;
342 else {
343 *to++ = ch;
344 left--;
345 }
346 }
347 written -= left;
348 }
349 update_vm_cache(inode, filp->f_pos, bh->b_data + (filp->f_pos & (SECTOR_SIZE-1)), written);
350 filp->f_pos += written;
351 if (filp->f_pos > inode->i_size) {
352 inode->i_size = filp->f_pos;
353 inode->i_dirt = 1;
354 }
355 fat_set_uptodate(sb,bh,1);
356 mark_buffer_dirty(bh, 0);
357 brelse(bh);
358 }
359 if (start == buf)
360 return error;
361 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
362 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
363 inode->i_dirt = 1;
364 return buf-start;
365 }
366
367 void fat_truncate(struct inode *inode)
368 {
369 int cluster;
370
371
372 if (IS_IMMUTABLE(inode)) return ;
373 cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
374 (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
375 MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
376 inode->i_dirt = 1;
377 }