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