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